zoukankan      html  css  js  c++  java
  • 第一章 编译预处理

                    课程目标

    了解嵌入式C语言编程特点和操作细节 结合嵌入式环境深入理解指针、数组和函数 提高编程实践和编程程序规范理解 熟悉C语言标准库应用和特点

                       课程结构图

                第一章

    第一章

    编译预处理与位运算

    编译预处理与位运算

                                                本章目标

    本章概述

    讲述宏定义的标准用法和位操作的基本应用

    了解预编译的概念,掌握宏定义的方法。

    了解“文件包含”与预处理的应用。 了解条件编译的几种形式。

    本章目标

    了解一些C语言特殊的宏定义 重点

    宏定义操作

                     本章结构

    编译预处理和位运算

    编译预处理和位运算 文件包含

    编译预处理 编译预处理

    宏定义 宏定义

    文件包含

    条件编译 条件编译

    预处理其他关键词

    预处理其他关键词

                      1 编译预处理与位运算

    编译预处理

    宏定义

    文件包含

    条件编译

    位运算

    其他预处理关键字

                                                          1.1编译预处理 作用:对源程序编译之前做一些处理,生成扩展C源程序

    种类

    格式:

    #define #ifdef #ifndef #include #if--#else--#endif等

    宏定义

    文件包含

    条件编译

    其他宏定义 #line #error #pragma

    “#”开头 占单独书写行 语句尾不加分号

                   1.2 宏定义

    #undef 无参数宏定义 有参数宏定义

                        1.2.1 #undef #undef定义指令删除前面定义的宏名字。

    表达一般形式为:

    例子

    #undef macro-name

    #define MICRO 1 #undef MICRO

                                 1.2.2 无参数宏定义

    宏体可缺省,表示宏名 定义过或取消宏体

    不带参数宏定义

    一般形式: #define 宏名 [宏体] 功能:用指定标识符(宏名)代替字符序列(宏体)

    如 #define YES 1

    #define NO 0

    #define PI 3.1415926

    #define OUT printf(“Hello,World”);

    例例#d#edfienfeineWWIDITDHTH8080 ()

    #d#edfienfeineLELNEGNTGHTHWWIDITDHT+H4+040 v a v r =a r L = E L NE GN TG HT * H2 * ; 2 ;

    if(x==YES) printf(“correct! ”); ()

    展开例后:#deifi(nxe==1P)I 3.14p1r5in9tf(“correct! ”);

    宏宏展展开开::vavr=ar8=0+8400+4*02;*2;

    else if (x==NO) printf(“error! ”);

    prinetfl(s“e2*iPf (Ix==%=f0 )”,PIp*r2in);tf(“error! ”); 例 #define MAX MAX+10 (×)

    宏展开:printf(“2*PI=%f ”,3.14159*2); 嵌入式家园 www.embedclub.com

    上海嵌入式家园-开发板商城 http://embedclub.taobao.com/

                                         1.2.2 不带参数宏定义 宏定义的规则

    宏名一般习惯用大写字母表示,以便与变量名相区别 宏定义不是C语句,不必在行末加分号 在进行宏定义时,可以引用已定义的宏名,可以层层替换。 只作字符替换,不分配内存空间。

    #define R 3.0

    #define PI 3.1415926 结果:

    #define L 2*PI*R #define S PI*R*R main()

    {

    L = 18.849556

    }

    嵌入式家园 www.embedclub.comprintf(“L=%f S=%f ”,L,S);

    上海嵌入式家园-开发板商城 http://embedclub.taobao.com/

    结果:

    L = 18.849556

    S = 28.274333

    S = 28.274333

                                           1.2.2 不带参数宏定义 宏定义的特点

    宏名一般习惯用大写字母表示 提高程序的通用性 宏名的有效范围为定义命令之后到本源文件结束 可以用#undef命令终止宏定义的作用域 宏定义只作简单的替换,不作正确性检查

                 1.2.2 不带参数宏定义 练习:

    定义一个宏,用于计算一年当中的秒数。定义一

     个宏,用于计算一年当中的秒数。

                                           1.2.3 带参数宏定义

    一般形式: #define 宏名(参数表) 宏体

    例 #define S(a,b) a*b ...........

    不能加空格

    area=S(3,2); 宏展开: area=3*2;

    宏展开:形参用实参换,其它字符保留

    宏体及各形参之间应加空格

    注意宏体的括号

    例 #define S (r) PI*r*r

    例 #define POWER(x) x*x

    相当于定义了不带参宏S,代表字符串“(r) PI*r*r” x=4; y=6;

    z=POWER(x+y);

    宏展开:z=x+y*x+y;

    一般写成: #define POWER(x) ((x)*(x))

    宏展开: z=((x+y)*(x+y)); 嵌入式家园 www.embedclub.com

    上海嵌入式家园-开发板商城 http://embedclub.taobao.com/

                                                       1.2.3 带参数宏定义 带参数宏定义的特点

    带参宏定义中,宏名和形参表之间不能有空格出现

    例如: #define MAX(a,b) (a>b)?a:b

    写为: #define MAX (a,b) (a>b)?a:b 将被认为是无参宏定义,宏名MAX代表字符串 (a,b)(a>b)?a:b

    在带参宏定义中,形式参数不分配内存单元,因此不必作类型定义

    在宏定义中的形参是标识符,而宏调用中的实参可以是表达式

    #define SQ(y) (y)*(y) main()

    {

    int a,sq;

    printf("input a number: ");

    scanf("%d",&a);

    sq=SQ(a+1);

    printf("sq=%d ",sq);

    在宏定义中,字符串内的形参通常要用括号括起来以避免出错

    }

                       1.2.3 带参数宏定义 带参的宏和带参函数很相似,但有本质上的不同

    带参宏 处理时间 编译时

    函数 程序运行时

    参数类型 处理过程

    无类型问题

    定义实参,形参类型 分配内存

    不分配内存

    简单的字符置换

    先求实参值,再代入形参 不变

    变长 运行速度 不占运行时间

    程序长度

    调用和返回占时间

                               1.2.3 带参数宏定义 带参的宏和带参函数很相似,但有本质上的不同

    函数例 宏定义例

    main() {

    #define SQ(y) ((y)*(y))

    int i=1;

    while(i<=5) printf("%d ",SQ(i++));

    main() {

    }

    SQ(int y) {

    int i=1; while(i<=5)

    return((y)*(y)); }

    printf("%d ",SQ(i++)); }

                                             1.3 文件包含 功能:一个源文件可将另一个源文件的内容全部包含进来

    函数例

    #include “file2.c” A

    file2.c

    嵌入式家园 www.embedclub.com

    <> 直接按标准目录搜索

    “” 先在当前目录搜索,再搜索标准目录 一般形式: #include “文件名”

    或 #include <文件名> 处理过程:预编译时,用被包含文件的内容取代该预处理命令,再对“包

    含”后的文件作一个源文件编译

    上海嵌入式家园-开发板商城 http://embedclub.taobao.com/

    B

    A file1.c file1.c

    file2.c

                                                1.3 文件包含

    被包含文件内容 源文件(*.c) 头文件(*.h)

    file3.h

    文件包含可嵌套

    file1.c A

    #include “file2.h”

    #include “file3.h”

    AB file1.c file2.h

    file3.h

    宏定义

    数据结构定义

    函数说明等

    file2.h

    C

                  1.3 文件包含 例子

    /* powers.h */

    #define sqr(x) ((x)*(x))

    #define cube(x) ((x)*(x)*(x)) #define quad(x) ((x)*(x)*(x)*(x))

    #include <stdio.h>

    #include "powers.h"

    #define MAX_POWER 10 int main()

    { intn;

    }

    printf("%2d %3d %4d %5d ",n,sqr(n),cube(n),quad(n)); 嵌入式家园 www.embedclub.com

    printf("number exp2 exp3 exp4 "); printf("---- ---- ----- ------ "); for(n=1;n<=MAX_POWER;n++)

    上海嵌入式家园-开发板商城 http://embedclub.taobao.com/

                                    1.3 文件包含 文件包含特点

    一个include命令只能指定一个被包含文件

    可以用双引号括起来,也可以用尖括号括起来。

    文件包含允许嵌套

    被包含文件(file2.h)与其所在的文件(file.c)在预编译之后已成为同一个文 件

                  1.4 条件编译 #if、#else、#elif #endif

    #ifdef和#ifndef

                    1.4.1 #if#else#elif #endif 条件编译指令中最常用的或许是#if,#else,#elif和#endif

    #if的一般形式是:

    #if constant-expression Statement sequence

    #endif

    #endif标记#if块的结束 例子:

    #ifdef COMPUTER_A #define INTEGER_SIZE 16

    #else

    # define INTEGER_SIZE 32

    #endif

                    1.4.1 #if#else#elif #endif 条件编译指令中最常用的或许是#if,#else,#elif和#endif

    #if的一般形式是:

    #if constant-expression Statement sequence

    #endif

    #endif标记#if块的结束 例子:

    #ifdef COMPUTER_A #define INTEGER_SIZE 16

    #else

    # define INTEGER_SIZE 32

    #endif

                    1.4.1 #if#else#elif #endif #else指令的作用与C语言的else相似,#if指令失败时它可

    以作为备选指令

    #else既是标记#if块的结束,也标记#else块的开始

    每个#if只能写一个#endif匹配

    例子:

    #include <stdio.h> #define MAX 100 int main(void)

    {

    }

    #if MAX>99

    printf(“Compiled for array greater than 99. ”);

    #else

    printf(“Complied for small array. ”);

    #endif return 0;

                  1.4.1 #if#else#elif #endif

    #elif指令的意思是“否则,如果”

    语法格式:

    #if expression Statement sequence

    #elif expression1 Statement sequence

    #elif expression2 ......

    #elif expression Statement sequence

    #endif

                          1.4.2 #ifdef#ifndef #ifdef --如果已定义

    #ifdef的一般形式如下: #ifdef 标识符

    程序段1 #else

    程序段2 #endif

    当所指定的标识符已经被#define命令定义过,则在程序编译阶段只编译 程序段1,否则编译程序段2。

                          1.4.2 #ifdef#ifndef #ifndef --如果已定义

    #ifdef的一般形式如下: #ifndef 标识符

    程序段1 #else

    程序段2 #endif

    作用是当所指定的标识符未被#define命令定义过,则在程序编译阶段只 编译程序段1,否则编译程序段2。它只是第一行与第一种形式不同。这 种形式与第一种形式的作用相反#ifndef

                1.4.2 #ifdef#ifndef #ifdef和#ifndef

    #inlucde <stdio.h> #define T 10

    int main(void)

    {

    #ifdef T

    printf(“Hi T ”);

    #else

    printf(“Hi anyone ”);

    #endif #ifndef M

    printf(“M Not Defined ”); #endif

    return 0; }

                          1.4.2 #ifdef#ifndef #if --如果已定义

    #if 的一般形式如下: #if 常量表达式

    程序段1 #else

    程序段2 #endif

    如常量表达式的值为真(非0),则对程序段1 进行编译,否则对程序段2进 行编译

                1.4.2 #ifdef#ifndef #if 例子

    #define R 1 main()

    {

    }

    float c,r,s;

    printf ("input a number: "); scanf("%f",&c);

    #if R

    r=3.14159*c*c;

    printf("area of round is: %f ",r); #else

    s=c*c;

    printf("area of square is: %f ",s); #endif

                阶段小节

      宏定义的特点和宏定义的取消   带参数宏定义要注意的几个细节

      条件编译主要应用在那几个方面,它有几种使用方法  Include 包含文件的两种方法和他们之间的区别特点

                      1.5 其他预处理关键字

    #error 使用defined #line #pragma

    #和## 预定义宏

                                   1.5.1 #error

    #error指令强制编译程序停止编译

    主要用于程序调试

    #error指令的一般形式是 #error error-message

    注意:

    宏串error-message不用双引号包围 可以自定义错误内容

                         1.5.2 使用defined 确定是否定义宏名字的方法

    defined操作符的一般形式如 defined macro-name

    确定宏MY是否定义:define与#ifdef: #if defined MY

    #ifdef MY

    感叹号”!”来反转相应的条件 #if !defined DEBUG

    #endif

    printf(“Final Version! ”);

                        1.5.3 #line

    #line指令改变__LINE__和__FILE__的内容 #line的一般形式

    #line number “filename” 主要用于调试和特殊应用

                1.5.4 ### 操作符#通常称为字符串化的操作符

    #include <stdio.h> #define mkstr(s) #s int main(void)

    {

    }

    printf(mkstr(I like C)); return 0;

    预处理程序把以下的语句:

    变成

    printf(mkstr(I like C));

    printf(“I like C”);

                   1.5.5 ### “##”可以把两个独立的字符串连接成一个字符串

    #include<stdio.h>

    #define SORT(X) sort_function # # X int main(void)

    }

    {

    结果:

    结果:

    char *array;

    int elements,element_size;.

    SORT(3) (array,elements,element_size);

    SORT(3) 转化为sort_function3 SORT(3) 转化为sort_function3

    SORT(3) (array,elements,element_size)转化为 SORT(3) (array,elements,element_size)转化为

    sort_function3(array,elements,element_size sort_function3(array,elements,element_size

    如果在运行时才能确定要调用哪个函数,可以利用 “##”运算符动态地构造要调用函数的名称。

                     1.5.6 预定义宏

    __DATE__ 进行预处理的日期(“Mmm dd yyyy”形

    式的字符串文字)

    __FILE__ 代表当前源代码文件名的字符串文字 __LINE__ 代表当前源代码中的行号的整数常量 __TIME__ 源文件编译时间,格式微“hh:mm:ss” __func__ 当前所在函数名

                  1.5.7 预定义宏 例子

    #include <stdio.h> #include <stdlib.h> void why_me();

    int main()

    void why_me() {

    {

    printf( "The file is %s. ", __FILE__ ); printf( "The date is %s. ", __DATE__ ); printf( "The time is %s. ", __TIME__ ); printf( "This is line %d. ", __LINE__ ); printf( "This function is %s. ",

    printf( "This function is %s ", __func__ ); printf( "The file is %s. ", __FILE__ ); printf( "This is line %d. ", __LINE__ );

    __func__ ); why_me(); return 0;

    }

    }

                阶段小节

      位操作几个运算操作的特点   位段的特点和位段数据的引用

      位段使用的规则

      C语言扩展宏定义几个具体应用

     调试

      ##与#   #define

                                    本章结构

    编译预处理和位运算

    编译预处理和位运算

    文件包含 文件包含

    讲述条件编译的三种应用方式

       和主要功能实现

    编译预处理 编译预处理

    #define定义的原则和注意事项 及应用

    宏定义 宏定义

    条件编译 条件编译

    预处理其他关键词

    预处理其他关键词

    预处理的基础操作方式

    讲述文件包含的特点和用处, 以及#include””<>的区别

    讲述了#error以及#pragma和 调试输入基本应用

                    本章总结

    宏定义特点和注意细节 条件编译特点和主要用处 文件包含的路径查询规则 C语言扩展宏定义的用法

                                           实验1 题目

    用宏定义来实现两个数取最大值

    注意事项

    ?运算符的运用 对参数的包含 define的语法特点

    实验结果

    掌握宏定义的具体应用,深化对宏定义的操作。

     git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

  • 相关阅读:
    hdu 1325 Is It A Tree?(并查集)
    hdu 1010 Tempter of the Bone(深搜+奇偶剪枝)
    hdu 1811 Rank of Tetris(并查集+拓扑排序)
    hdu 4324 Triangle LOVE(拓扑排序)
    使用hibernate和struts2实现分页功能
    struts2生成随机验证码图片
    Spring学习篇:IoC知识整理(一)
    HibernateTools工具通过hbm文件自动生成ddl、pojo等代码
    使用struts2的token机制和cookie来防止表单重复提交
    Spring学习篇:AOP知识整理
  • 原文地址:https://www.cnblogs.com/askDing/p/5443585.html
Copyright © 2011-2022 走看看