• 宏定义之二(连接符,可变參数,文件名称,行号,函数名)


    宏的高级使用--##,__VA_ARGS__, __FILE__, __FUNCTION__等

    转自 http://blog.csdn.net/yiya1989/article/details/7849588


    先说一下本文中会提到的内容:##,__VA_ARGS__, __FILE__, __LINE__ , __FUNCTION__等
    宏变量:
    先举一个样例,会用到上面这些宏:
    1. #define myprintf(...) printk("[lch]:File:%s, Line:%d, Function:%s,"   
    2.      __VA_ARGS__, __FILE__, __LINE__ ,__FUNCTION__);  

    此处的 #define 的作用是将 myprintf( )换成后面那一大串的内容,而括号内 ... 的内容原样抄写在 __VA_ARGS__ 的位置。终于输出例如以下:

    [lch]:File:arch/arm/mach-omap2/board-omap3wscec-camera.c, Line:163, Function:beagle_cam_init,camera init!

    解析:

    1)__VA_ARGS__:整体来说就是将左边宏中 ... 的内容原样抄写在右边 __VA_ARGS__ 所在的位置。它是一个可变參数的宏,是新的C99规范中新增的,眼下似乎仅仅有gcc支持(VC从VC2005開始支持)。要注意的是,printf 的输出格式是括号内左边是字符串,右边是变量,并且右变量与左输出格式是一一相应的。所以在上面那个样例中, __VA_ARGS__仅仅能是一些不含不论什么变量的字符串常量。由于上面的样例中若__VA_ARGS__含有变量,整个printf的输出与变量便不能一一相应,输出会出错。

    假设不过替换函数名,可用例如以下方式,此时对__VA_ARGS__无不论什么特殊要求:#define myprintf(...) printk( __VA_ARGS__),在调试程序时能够这样用:

    1. #ifndef LOG_NDEBUG_FUNCTION  
    2. #define LOGFUNC(...) ((void)0)  
    3. #else  
    4. #define LOGFUNC(...) (printk(__VA_ARGS__))  
    5. #endif  
    2) __FILE__ :宏在预编译时会替换成当前的源文件名称
    3) __LINE__:宏在预编译时会替换成当前的行号
    4) __FUNCTION__:宏在预编译时会替换成当前的函数名称
    5)类似的宏还有 __TIME__,__STDC__, __TIMESTAMP__等,就全然当一个变量来使用就可以。

    宏连接符##:
    举个样例:宏定义为#define XNAME(n) x##n,代码为:XNAME(4),则在预编译时,宏发现XNAME(4)与XNAME(n)匹配,则令 n 为 4,然后将右边的n的内容也变为4,然后将整个XNAME(4)替换为 x##n,亦即 x4,故 终于结果为 XNAME(4) 变为 x4.
    代码例如以下:
    1. #include <stdio.h>  
    2. #define XNAME(n) x ## n  
    3. #define PRINT_XN(n) printf("x" #n " = %d/n", x ## n);  
    4. int main(void)  
    5. {  
    6. int XNAME(1) = 14; // becomes int x1 = 14;  
    7. int XNAME(2) = 20; // becomes int x2 = 20;  
    8. PRINT_XN(1); // becomes printf("x1 = %d,", x1);  
    9. PRINT_XN(2); // becomes printf("x2 = %d/n", x2);  
    10. return 0;  
    11. }  
    输出为:x1 = 14, x2 = 20





    PS:编译过程:
    1,扫描解析文件
    2,预处理(宏在此时处理,该替换的文字会被替换)
    3,对处理过的源码进行汇编,输出汇编语言的代码(C语言的控制流程被处理)
    4,编译为二进制目标文件
    5,与程序库进行链接,输出终于的程序文件
    (宏 和 C语言在不同的阶段处理运行)
  • 相关阅读:
    Asp.net导出Excel文件
    Ext.Net 使用总结之GridPanel中的选中行
    Ext.Net 使用总结之查询条件中的起始日期
    使用python crontab设置linux定时任务
    JSON Serialization/Deserialization in C#
    redis 基本数据类型-列表(List)
    redis 基本数据类型-字符串(String)
    使同一个server上不同port的django应用可在同一个浏览器上打开
    django server之间通过remote user 相互调用
    使用python实现短信PDU编码
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4008236.html
Copyright © 2020-2023  润新知