• 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标识符的时候用的都是大写,这是我们的约定】

    实例代码:

    1. #define MAX 100;
    2. #define STR "澜色海湾"
    3. extern int add(int x , int y);
    4. int main() {
    5. int max = MAX;
    6. char str[] = STR;
    7. printf("%d\n",max);
    8. printf("%s\n",str);
    9. return 0;
    10. }

            #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

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

    1. #define SQUARE(x) x*x
    2. int main() {
    3. int ret = SQUARE(5+1);
    4. printf("%d",ret);
    5. return 0;
    6. }

            咋一看,我们可能会认为会输出 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 定义的符号的时候,字符串常量的内容并不被搜索【就是字符串常量不会被宏替换掉 】;例如->

    1. #define MAX 100;
    2. int main() {
    3. printf("MAX = %d" , MAX);
    4. return 0;
    5. }

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

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

    预处理操作符 # 和 ##

    先来看看预处理操作符 #

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

    实例代码如下所示 ->

    1. #define PRINT(x) printf("the value of "#x"is %d\n",x);
    2. int main() {
    3. int a = 10;
    4. int b = 20;
    5. PRINT(a);
    6. PRINT(b);
    7. return 0;
    8. }

             此时,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   

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

    ## 的作用 ->

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

    举个例子 ->

    1. #define CAT(X,Y) X##Y
    2. int main() {
    3. int lanSeHaiWan = 100;
    4. printf("%d\n",CAT(lanSe,HaiWan));
    5. return 0;
    6. }

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

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

            会被替换成 ->

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

            所以输出的结果依旧是 100

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

  • 相关阅读:
    AI Agent新对决:LangGraph与AutoGen的技术角力
    车载电子电器防水防尘等级介绍
    新装机电脑网速特别慢
    基于QT的指挥猫猫打架玩耍的小游戏设计
    LeetCode-剑指35-复杂链表的复制
    彻底掌握Python中 * 号
    【AIGC】FaceChain:发挥生成式内容的无限可能性
    深度学习自编码器 - 引言篇
    Ubuntu20.04 交叉编译librtmp
    JAVA 版多商家入驻 直播带货 商城系统 B2B2C 商城免费搭建之 B2B2C产品概述
  • 原文地址:https://blog.csdn.net/m0_52433668/article/details/127037687