34.0、C语言——C语言预处理(2) - 预编译指令

34.0、C语言——C语言预处理(2) - 预编译指令

预处理详解:

预定义符号:

        __FILE__                // 进行编译的源文件;

        __LINE__                // 文件当前的行号;

        __DATE__               // 文件被编译的日期;

        __TIME__                // 文件被编译的时间;

        __STDC__               // 如果编译器遵循 ANSI C,其值为1 ,否则未定义 ;经测试VS编译器中这个是未定义的;

这些预定义符号都是C语言内置的,举个例子:

printf("file:%s line:%d\n",__FILE__,__LINE__);

预处理指令:

# 开头的都叫做预处理指令,比如说 -> 

        1. #include

        2. #define

        3. #pragma

        4. #if

        5. #endif

        6. ifdef

        7. #line 

        8. .........

#define 定义标识符

        语法:#define name stuff   【我们在定义#define标识符的时候用的都是大写,这是我们的约定】

实例代码:

#define MAX 100;
#define STR "澜色海湾"

extern int add(int x , int y);
int main() {
	int max = MAX;
	char str[] = STR;
	printf("%d\n",max);
	printf("%s\n",str);
	return 0;
}

        #define 后面可以是 标识符名 也可以是 一段代码,无论是什么,都会在预处理阶段将代码中的相应的 标识符 进行替换;  

问题:在 #define后面需要加 分号;吗?

        不需要,因为在#define 后面加上分号,当预处理去替换的时候会把 分号 一起替换过去,有可能会出现一些问题;

#define 定义宏

        #define 机制包括一个规定,允许把参数替换到文本中,这种实现通常称为宏 ( macro ) 或定义宏 ( define macro );

        下面是宏的声明方式:【定义宏的时候都是大写,这是我们的约定】

        #define name ( parament - list ) stuff 其中的 parament - list 是一个由逗号隔开的符号表,他们可能出现在 stuff 中;

        注意:参数列表的左括号必须与name紧邻;如果两者之间有任何空白、空格存在,参数列表就会被解释为 stuff 的一部分;         

        如:

#define SQUARE(x) x * x //这里指的是会将 SQUARE(x) 替换成 x 的平方

这个宏接收一个参数 x,如果在上述声明之后,你把

SQUARE ( 5 );

置于程序中,预处理器就会用下面这个表达式替换上面的表达式 ->

5 * 5

警告:这个宏存在一个问题 ,观察下面的代码段:

#define SQUARE(x) x*x

int main() {
	int ret = SQUARE(5+1);
	printf("%d",ret);
	return 0;
}

        咋一看,我们可能会认为会输出 36 ,因为 6 的平方等于 36;
        但是实际上输出的是 11;

为什么呢?

        因为这里不是传参【 传参应该是 int x 而不是单单一个 x 】,而是替换,他会完完全全把 x 替换成  5+1,所以计算的是 5 + 1 * 5 + 1 根据计算优先级得出结果为 11;

#define的替换规则:

在程序中扩展 #define 定义符号和宏时,需要涉及几个步骤?

        1. 在调用宏时,首先对参数进行检查,看看是否包含任何由 #define 定义的符号;如果是,他们首先被替换;【例如:DOUBLE(MAX+MAX),此时DOUBLE和MAX都是宏,那么由于MAX是DOUBLE的参数,所以先将MAX替换,再去替换DOUBLE】;

        2. 替换文本随后被插入到程序中原来文本的位置;对于宏,参数名被他们的值替换;

        3. 最后,再次对结果文件进行扫描,看看他是否包含任何由 #define 定义的符号;如果是,就重复上述处理过程;

注意:

        1. 宏参数和#define定义中可以出现其他 #define 定义的变量;但是对于宏,不能出现递归;

        2. 当预处理器搜索 #define 定义的符号的时候,字符串常量的内容并不被搜索【就是字符串常量不会被宏替换掉 】;例如->

#define MAX 100;
int main() {
    printf("MAX = %d" , MAX);
    return 0;
}

        printf() 中的第一个MAX不会被替换,第二个会被宏替换掉;
 

接下看两个比较奇怪的东西:

预处理操作符 # 和 ##

先来看看预处理操作符 #

        如何把宏的参数插入到字符串中?

实例代码如下所示 ->

#define PRINT(x) printf("the value of "#x"is %d\n",x);
int main() {
    int a = 10;
    int b = 20;
    PRINT(a);
    PRINT(b);
    return 0;
}

         此时,PRINT(a); 会被替换成 printf ( " the value of " "a" " is %d\n " , a );      #x 并没有把 a 替换成 10,而是替换成了字符串 "a"; 

        输出的结果就是   the value of a is 10
                                    the value of b is 10   

预处理操作符 ## 又是什么呢? 

## 的作用 ->

## 可以把位于它两边的符号合成一个符号;他允许宏定义从分离的文本片段创建标识符;

举个例子 ->

#define CAT(X,Y) X##Y

int main() {
    int lanSeHaiWan = 100;
    printf("%d\n",CAT(lanSe,HaiWan));
    return 0;
}

        执行代码后,这段代码中的:

printf("%d\n",CAT(lanSe,HaiWan));

        会被替换成 ->

printf("%d\n",lanSe##HaiWan);
//由于 ## 会把两端的符号合并成为一个,其实就相当于是 ->
printf("%d\n",lanSeHaiWan);

        所以输出的结果依旧是 100

注:这样的连接必须产生一个合法的标识符;否则结果就是未定义的;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值