#和##用法总结

C语言中如何使用宏C(和C++)中的宏(Macro)属于编译器预处理的范畴,一般在编译期间就会使用和替换,下面就是在宏定义中使用#和##的情况说明。

1. 关于#和##

#的用法
在C语言的宏定义中,#的功能是将其后面的宏参数转化为字符串,简单说就是在对它所引用的宏变量 通过替换后在其左右各加上一个双引号。比如下面代码中的宏定义:

#define ADDSTR(str)    do{ fprintf(stderr, "add strings: " #str "/n"); }   while(0)
ADDSTR(hello);

这样上述ADDSTR(hello);就表示如下代码运行,

do{ 
	fprintf(stderr, "add strings: " "hello" "/n");
	}  while(0);

##的用法
##被称为连接符(concatenator),用来将两个Token连接为一个Token。注意这里连接的对象是Token就行,而不一定 是宏的变量。比如你要做一个菜单项命令名和函数指针组成的结构体的数组,并且希望在函数名和菜单项命令名之间有直观的、名字上的关系。那么下面的代码就非常实用:

#define USER_DATA_DEFINE(type,name)                                     \
                                                                        \
type name __attribute__((section("NO_INIT_WITH_SAVE"), zero_init));     \
                                                                        \
typedef struct                                                          \
{                                                                       \
    char      name[NAME_LEN];                                           \
    type      *address;                                                 \
    uint32_t  length;                                                   \
}Var##name##_t;                                                         \

USER_DATA_DEFINE(USER_DATA_CTRL_WORD_T,        user_data_ctrl_word);

上述的USER_DATA_DEFINE(USER_DATA_CTRL_WORD_T, user_data_ctrl_word);语句就可以等效为以下代码:

USER_DATA_CTRL_WORD_T  user_data_ctrl_word __attribute__((section("NO_INIT_WITH_SAVE"), zero_init));
typedef struct  {
	char      name[NAME_LEN]; 
	type      *address; 
	uint32_t  length;
}Varuser_data_ctrl_word_t;

因此可以使用##符号来使代码看起来更加简单明了;

##的特殊用法

在说明这种特殊用法时,先解释下…的作用;…在C宏中称为变参宏。比如:

#define myprintf(templt,...) fprintf(stderr,templt,__VA_ARGS__)

// 或者

#define myprintf(templt,...) fprintf(stderr,templt,args)

第一个宏中由于没有对变参起名,我们用默认的宏__VA_ARGS__来替代它。第二个宏 中,我们显式地命名变参为args,那么我们在宏定义中就可以用args来代指变参了。同C语言的stdcall一样,变参必须作为参数表的最有一项出 现。当上面的宏中我们只能提供第一个参数templt时,C标准要求我们必须写成:
myprintf(templt,); 的形式。
这时的替换过程为:
myprintf(“Error!/n”,);
替换为:
fprintf(stderr,“Error!/n”,);

这是一个语法错误,不能正常编译。
但是如果我们定义成如下形式就不会报错:

#define myprintf(templt, ...) fprintf(stderr,templt, ##__VAR_ARGS__)

这时,##这个连接符号充当的作用就是当__VAR_ARGS__为空的时候,消除前面的那个逗号。那么此时的翻译过程如下:
myprintf(templt);
被转化为:
fprintf(stderr,templt);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值