C语言预处理功能 关于字符串化和符号粘贴

在C语言开发中,宏定义是一个很是有用的工具,它能够使咱们的代码更容易理解,更容易维护。如查一个常量在多处被使用,且从此可能会根据不一样须要而 修改的话,将其define一下那是再好不过了。除此以外,宏定义还有其余的功能,了解它,将更好地辅助咱们开发C程序。先看个例子:工具

#define Conn(x,y)测试

x##y.net

#define ToString(x)调试

#xip

#define ToChar(x)开发

#@x 字符串

这几个宏定义中分别用到了“##”、“#”,“#@”它们的功能分别是:get

一、粘接操做符##——链接两个宏名,注意所链接的是宏名,而不是其所指代的值;编译器

如int Conn(a,b);定义了一个int型变量ab,之后能够直接调用ab,而没必要采用Conn(a,b)的形式;string

printf(Conn("ab","cd"));输出结果为:abcd

可是:

#define M 0 #define var(x) Var_##x ... int var(M);//此处定义了什么?

根据ANSI/ISO C,##操做符只是简单地粘接两个宏名,则int var(M)定义的应该就是Var_M,据测试,这一点是没有问题的。但在一些比较古老的C编译环境中,也有可能定义的是Var_0,好比在TC 2.0中测试发现“Var_0=0”可编译经过,而“Var_M=0”出现ERROR。

二、字符串化操做符#——将宏名转化为字符串

如printf(ToString(var1));输出结果为:var1。var1能够是一个已定义的变量名,也能够是一个从未出现的字符组合

相似地,如有:

#define STR 0

...

printf(Tostring(STR));//

当前流行编译环境会输出STR,而TC 2.0则会输出0。

三、字符化操做#@——将宏名转化为字符,注意:早期编译器可能不支持

如:

char c;

c = ToChar(1);//c = '1'

c = ToChar(a);//c = 'a'

若是提供的宏中不止一个字符(注意,不能超过4个,不然编译器报错),则转化结果为最后一个字符,如

c = ToChar(abc);//c = 'c'

c = ToChar(abcd);//c= 'd'

c = ToChar(abcde);//ERROR

总结一下,关于其用法是本身总结的,确定不全。

一、使用中遵循ANSI C中规定,但要记得编译通不过是多是早期编译器不支持C标准的问题;

二、##操做可应用在变量定义中,若程序开发中遇到要定义一大堆变量,且这些变量具备相同的前缀时,##很显得尤其重要,它能够使代码更加整洁,且减小了出错的机率。若是一旦后来发现须要批量修改变量前缀,你会庆幸本身使用了这么一件利器;

三、#操做符可用于调试时将变量名输出,可配合##一块儿使用,如定义#define CHECK_VAR(x,fmt) printf(#x " = " #fmt "\n", x),则CHECK_VAR(var1,%d)至关于printf("var = %d\n", var1);

Tips:

一、ANSI C中规定若宏定义名出如今引号(' '或" ")中,则不进行替换,但有些早期编译器的处理可能有所不一样,如#define CTRL(c) (‘c’ & 37),按照标准CTRL(d)被扩展成('c' & 37)。显然,这没有完成做者的本意,它在某些编译器下碰巧能工做不过是个意外,实际使用中应避免。

二、字符串的链接没必要使用##这么麻烦,实际中两个字符串常量能够直接写到一块儿,如printf("ab""cd")输出abcd。或在使 用##宏定义时,能够用printf(ToString(str) "\n");输出字符串后换行,之前不敢这样用,后来试验了下发现还比较好使,固然直接用puts也可完成一样功能。

三、若要使#或##转换的是宏字符常量的值也不是其名字,能够使用间接方法,如:

#define ToString(x) #x

#define Xstr(x) ToString(x)

#define STR1 STR2 ...

printf(Xstr(STR1));//输出结果是STR2而非STR1