C语言中的宏(macro)

 

在C语言中,宏(macro)也是一个挺有意思的东西。C语言中的宏由预处理指令 #define 来定义。说到这里,再简单了解下预处理。在编译器对程序处理的过程中,在字符到源字符的映射和逻辑行处理后就会对文本进行划分,划分出预处理的语言符号(token)序列及空白字符和注释序列,然后就是预处理的过程了。预处理指令 #define是一个明显常量定义指令,用于定义符号常量(symbolic constant)以及明显常量(manifest constant)。每条#define语句都可以分为三个组成部分:#define、macro、替换列表(replacementlist)

宏(macro)的命名规则遵从C语言变量的命名规则。预处理在编译之前,宏在此过程中会被展开,也就是被替换成相应的替换列表(replacement list)中的文本。通常,宏的替换列表(replacementlist)会被视为语言符号(token)型字符串,即无论是否包含空格或其他符号都会被视为一个独立的词(word)。

简单宏,格式:#define  标识符 替换列表。通常用于定义一些简单的符号常量。其作用可使得长须变得更为易读和易维护。类函数宏(cunction-like macro),格式:#define 标识符(x1, x2,…,xn)替换列表。其作用和函数类似,但是类函数宏最终都会成为内联的函数代码,在某些情况下对代码的质量有较好的提升。

宏定义中的“#”运算符和“##”运算符。#运算符将一个宏的参数转换为字符串字面量(字符串字面量(string literal)是指双引号引住的一系列字符,双引号中可以没有字符,可以只有一个字符,也可以有很多个字符),简单说就是在对它所引用的宏变量通过替换后在其左右各加上一个双引号. 它仅允许出现在带参数的宏的替换列表中。"##"被称为 连接符(concatenator),它是一种预处理运算符, 用来把两个语言符号(token)组合成单个语言符号。 这里的语言符号不一定是宏的变量。并且”##”不能作为第一个或最后一个元素存在。

可变宏:…和__VA_ARGS__。在这里宏的参数列表中的最后一个参数可以为省略号,预定义宏__VA_ARGS__就能够用在替换部分中,用以代表省略号代表的内容。例如:

#define P(…) printf (__VA_ARGS__)
P(“hello”);      //会被展开成 printf(“hello”);
P(“w=%d, s=$%.2f\n”,w,s);//会被展开成printf(“w=%d,s=$%.2f\n”,w,s);

    C语言中的一些预定义宏。在C语言中预定义了一些宏,这些宏主要是提供当前编译的信息。例如:__LINE__(被编译的文件的行数)、__FILE__(被编译的文件的名字)、__DATE__(编译的日期(格式"Mmm dd yyyy")、__TIME__(编译的时间[格式"hh:mm:ss"])、__STDC__(如果编译器接受标准C,那么值为1)。这里只对部分预定义宏做简单描述,具体就不过多坠诉了。

    当然,宏(macro)并不是这简单的三两句就能说完的,想要在了解的,可以去查找相应的资料,加以了解。