目录
  • C 预处理器
    • 1.取消已定义宏
    • 2.使用#ifdef来调试
  • 常用预定义宏
    • 预处理器运算符 
      • 1.宏延续运算符
      • 2.字符串常量化运算符#
      • 3.标记粘贴运算符##
    • 参数化的宏
      • 总结

        C 预处理器

        C 预处理器不是编译器的组成部分,但是它是编译过程中一个单独的步骤。简言之,C 预处理器只不过是一个文本替换工具而已,它们会指示编译器在实际编译之前完成所需的预处理。

        指令 描述
        #define 定义宏
        #include 包含一个源代码文件
        #undef 取消已定义的宏
        #ifdef 如果宏已经定义,则返回真
        #ifndef 如果宏没有定义,则返回真
        #if 如果给定条件为真,则编译下面代码
        #else #if的替代方案
        #elif 如果前面的 #if 给定条件不为真,当前条件为真,则编译下面代码
        #endif 结束一个 #if……#else 条件编译块
        #error 当遇到标准错误时,输出错误消息
        #pragma 使用标准化方法,向编译器发布特殊的命令到编译器中

        1.取消已定义宏

        demo.h文件代码如下

        #ifndef     __DEMO_H_
        #define    __DEMO_H_
        
        
        #define PAI 3.14
        
        
        #endif // __DEMO_H_
        
        #include <stdio.h>
        #include "demo.h"
        
        /* 在 #include 与 main 函数中间区域使用#undef来取消以定义的宏,然后重新定义宏 */
        
        #undef PAI
        #define PAI 33.14
        
        
        int main()
        {
            printf("PAI = %G\n", PAI);
        }
        
        /*
        输出结果
        PAI = 33.14
        */
        

        2.使用#ifdef来调试

        #ifdef DEBUG
        
        /* 你的调试代码 */
        
        #endif // DEBUG
        

        如果定义了 DEBUG,则执行处理语句。在编译时,如果您向 gcc 编译器传递了 -DDEBUG 开关量,这个指令就非常有用。它定义了 DEBUG,您可以在编译期间随时开启或关闭调试。

        常用预定义宏

        描述
        __DATE__ 当前日期,一个以 “MMM DD YYYY” 格式表示的字符常量。
        __TIME__ 当前时间,一个以 “HH:MM:SS” 格式表示的字符常量。
        __FILE__ 这会包含当前文件名,一个字符串常量。
        __LINE__ 这会包含当前行号,一个十进制常量。

        预处理器运算符 

        1.宏延续运算符

        \一个宏通常写在一个单行上。但是如果宏太长,一个单行容纳不下,则使用宏延续运算符\

        #include <stdio.h>
        
        
        #define PAI  \
        
                        3.1415926
        
        int main()
        {
            printf("%.8f\n", PAI);
        }
        

        2.字符串常量化运算符#

        在宏定义中,当需要把一个宏的参数转换为字符串常量时,则使用字符串常量化运算符#。在宏中使用的该运算符有一个特定的参数或参数列表。就是把宏的参数变成字符串。

        #include <stdio.h>
        
        
        #define PAI 3.1415926
        //字符串常量化
        #define CONVERT_TO_STR1(arg) "字符串常量化:" #arg
        //字符串常量化
        #define CONVERT_TO_STR2(arg) CONVERT_TO_STR1(arg)
        
        int main()
        {
            printf("%s\n", CONVERT_TO_STR1(ABC));
            printf("%s\n", CONVERT_TO_STR1(PAI));
            printf("%s\n", CONVERT_TO_STR2(PAI));
        }
        
        /*
        输出结果
        字符串常量化:ABC
        字符串常量化:PAI
        字符串常量化:3.1415926
        */
        

        这里有几点需要提一下。

        1.宏定义中,当有多个字符串需要连接时,以空格来隔开每一个字符串即可。

        2.当需要把一个宏字符串常量化时,需要按照先定义一个宏函数1,然后再定义一个宏函数2,然后宏函数2调用宏函数1即可,例如CONVERT_TO_STR2调用CONVERT_TO_STR1

        3.标记粘贴运算符##

        宏定义内的标记粘贴运算符(##)会合并两个参数。它允许在宏定义中两个独立的标记被合并为一个标记。

        #include <stdio.h>
        
        
        #define PRINTF1(arg) printf("var" #arg "  = %d\n" , var##arg)
        
        int main()
        {
            int var1 = 20;
            PRINTF1(1);
        }
        
        
        

        /*
        输出结果
        var1  = 20
        */

        参数化的宏

        使用注意点

        用宏定义时,含参数时,参数本身要加(),此外,对参数的操作整体也要加()。

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

        使用宏函数的时候不要使用++/--运算符

        #include <stdio.h>
        
        
        #define MIN(A,B) ((A)<(B)?(A):(B))
        
        int main()
        {
            char *p="ghi";
            char a;
            a=MIN(*p++,'f');//不要使用自增/自减运算符
            printf("%c\n",a);
        }
        
        
        

        /*
        输出结果
        f
        */

        另,宏定义实现指定大小的交换:

        #define SWAP(a, b, size)    \
        
            unsigned int __size = (size);    \
        
            char *__a = (a), *__b = (b);    \
        
            do    \
        
            {    \
        
                char __tmp = *__a;    \
        
                *__a++ = *__b;    \
        
                *__b++ = __tmp;    \
        
            } while (--__size > 0);
        

        总结

        本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注的更多内容! 

        声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。