怎么样做网站管理员,重庆网上房地产查询,上海建筑设计院有限公司是国企吗,百度图片搜索图片识别C语言的宏系统相当强大#xff0c;它允许使用##符号来处理预处理期的文本替换。这种用法被称为标记连接#xff08;token pasting#xff09;操作#xff0c;其结果是将两个标记紧紧地连接在一起#xff0c;而省略掉它们之间的所有空格。在复杂的宏定义中#xff0c;运用…
C语言的宏系统相当强大它允许使用##符号来处理预处理期的文本替换。这种用法被称为标记连接token pasting操作其结果是将两个标记紧紧地连接在一起而省略掉它们之间的所有空格。在复杂的宏定义中运用##可以有效地生成新的标识符或调整代码的结构。对##符号的深入理解可以帮助编写出更高效、更灵活的代码但同时也需要注意其可能带来的复杂性和可读性问题。
##运算符也叫连接运算符也称胶水运算符预处理程序把出现在##两侧的参数合并成一个符号通常用于宏参数的连接。
基本应用 将两个符号连接到一起。
#define ARM_CONNECT(__A, __B) __A##__B//如下方式使用这个宏int ARM_CONNECTint,5;
//最终被展开为int int5;#define uint16Array(name,size) uint16_t Array##name[size];
//如下方式使用这个宏uint16ArrayUartTx,128;
//最终被展开为uint16_t ArrayUartTx[128];说明 Array与name是没有天然的分割的要将Array于name所代表的内容粘结在一起就需要使用“##”运算符的帮助。 name与“[”具有天然分隔的编译器不会认为name与[“是连接在一起的因此这里并不需要使用”##运算符如果你这么做了预编译器会毫不犹豫的告诉你语法错误。 2. 基于C99的扩展应用 一般应用于带可变参数的宏定义中比如
//如下宏定义
#define log(__STRING, ...) printf(__STRING, __VA_ARGS__)
//我们调用
log(output\r\n);
log( Cycle Count : %d, total_cycle_cnt);
//会被展开为
printf(output\r\n,);
printf( Cycle Count : %d, total_cycle_cnt);看似没有问题注意到一个细节没有在第一个printf()的最后多了一个,“。虽然有些编译器例如GCC并不会计较也许就是一个warning但是在ANSI-C99标准引入可变参数宏的时候又贴心了加了一个不那么起眼的语法当下面的组合出现时 ”,##VA_ARGS如果__VA_ARGS__是一个空字符串则前面的逗号,会一并被删除掉。因此上面的宏可以改写为
//如下宏定义
#define log(__STRING, ...) printf(__STRING, ##__VA_ARGS__)
//我们调用
log(output\r\n);
log( Cycle Count : %d, total_cycle_cnt);
//会被展开为
printf(output\r\n); //无可变参数没有后面的逗号了
printf( Cycle Count : %d, total_cycle_cnt); //有参数逗号依旧存在结合逗号表达式和##连接符的高级应用 我们看arm-2d里面大量使用了这种特征用来给函数提供初始化默认参数。如下
//定义一个宏
#define arm_2d_scene_watch_init(__DISP_ADAPTER_PTR, ...) \__arm_2d_scene_watch_init((__DISP_ADAPTER_PTR), (NULL, ##__VA_ARGS__))
//函数的原型
extern user_scene_watch_t *__arm_2d_scene_watch_init( arm_2d_scene_player_t *ptDispAdapter, user_scene_watch_t *ptScene);
//调用arm_2d_scene_watch_init(DISP0_ADAPTER);
//宏被替换为__arm_2d_scene_watch_init(DISP0_ADAPTER,NULL); //增加了一个默认参数NULL如上的代码在使用宏arm_2d_scene_watch_init的时候只传递了一个参数,但是最终替换后自动增加了一个参数。怎么做到的呢 看看逗号表达式 (NULL, ##VA_ARGS) 第一种情况 __VA_ARGS__为空那么这个表达是的值就是NULL。 第二种情况 __VA_ARGS__为非空那么这个表达的值就是可变参数传递进来的值。
比如带第二个参数的调用
//调用arm_2d_scene_watch_init(DISP0_ADAPTERbuffer);
//宏被替换为__arm_2d_scene_watch_init(DISP0_ADAPTER,buffer);