首页 > 代码库 > C语言中宏定义使用方法详解
C语言中宏定义使用方法详解
C语言中的宏替换详解
首先看一个问题:
#include <stdio.h>
#define PRINT_CLINE() printf("%d", ______)
int main(void)
{
PRINT_CLINE();
PRINT_CLINE();
return 0;
}
在横线处填上适当的代码,使得上面这段代码的输出为34。
我想一般人看到这个问题的时候头脑里都没有明确的思路来解答这个它。我看到这个问题的时候想出了各种办法来解答它,最终还是没有通过编译器的检查,比如我想过的其中一个办法是:
(int static i=2, i++)
想着在这个位置定义一个static变量,并且赋上初值为2,最后在加上一个i++,根据逗号运算符的运算规则,整个表达式的值应该是最后一项的值,想法确实很完美,但是这样是通不过编译器的!在这个位置使用一条定义变量的语句是不合法的!想了很久实在想不出来办法了。于是重新整理了宏定义的使用方法,终于找到了答案。下面一步步来说宏定义的使用方法:
1.最简单的替换
#defind Pi 3.14159
上面的这条语句就是比较常用的简单替换了,在预处理阶段,程序代码中出现Pi的地方都被替换为后面的3.14159。
2.带参数的宏替换
#define MAX(a, b) (a)>(b)?(a):(b)
这个就是带参数的宏替换了,在代码中使用MAX宏的时候,括号内部的参数会跟随到宏替换中。当然这个替换需要注意的地方就是记得为每个参数加上(),不然可能会产生边际效应。
3.字符替换符:#@
先看下面的这段代码:
#include <stdio.h>
#define PT_CHAR(x) printf("%c", #@x);
int main(void)
{
PT_CHAR(d);
return 0;
}
程序的输出为d。或许你会问,那直接将宏定义中的#@x用x替换掉不就可以了么,粗略的一看这样的说法确实是可以的,但是宏替换的时候PT_CHAR(d)编译器会认为d是一个传递的参数,既然d并非一个常量,那么编译器就只好认为它是一个变量了,但是这样的话问题就出来了,d并没有定义过!
4.字符串宏替换符:#
这个跟上面的有点类似了,比如下面的两行代码片段:
#define PT_STRING(x) printf("%s", #x)
PT_STRING(Hello!);
如果想要达到输出为Hello!的目的,就要使用#x,如果不使用的话根据前面的分析,编译器会把Hello!整体理解为一个变量,但是即便这样理解的话,这个!也是不能作为变量的一部分的啊,所以编译器会报出比较多的错误。
5.连接宏替换符:##
#define p(n) printf("symbol"#n"=%d", symbol##n)
int symbol9 = 9;
p(9);
上面的输出为symbol9=9,symbol##n将symbol和n(也就是传递过来的9)连接起来,构成了变量symbol9。
6.ANSI标准中的几个标准预定义宏
__LINE__:在源代码中插入当前源代码行号;
__FILE__:在源文件中插入当前源文件名;
__DATE__:在源文件中插入当前的编译日期
__TIME__:在源文件中插入当前编译时间;
__STDC__:当要求程序严格遵循ANSI C标准时该标识被赋值为1;
__cplusplus:当编写C++程序时该标识符被定义。
看到这里,上面的问题答案也就出来了,标准预定义宏中的__LINE__代表了源代码在改代码中的行号,使用这个宏就可以很方便的实现上面的功能了。
答案:#define PRINT_CLINE() printf("%d", __LINE__-4)
首先看一个问题:
#include <stdio.h>
#define PRINT_CLINE() printf("%d", ______)
int main(void)
{
PRINT_CLINE();
PRINT_CLINE();
return 0;
}
在横线处填上适当的代码,使得上面这段代码的输出为34。
我想一般人看到这个问题的时候头脑里都没有明确的思路来解答这个它。我看到这个问题的时候想出了各种办法来解答它,最终还是没有通过编译器的检查,比如我想过的其中一个办法是:
(int static i=2, i++)
想着在这个位置定义一个static变量,并且赋上初值为2,最后在加上一个i++,根据逗号运算符的运算规则,整个表达式的值应该是最后一项的值,想法确实很完美,但是这样是通不过编译器的!在这个位置使用一条定义变量的语句是不合法的!想了很久实在想不出来办法了。于是重新整理了宏定义的使用方法,终于找到了答案。下面一步步来说宏定义的使用方法:
1.最简单的替换
#defind Pi 3.14159
上面的这条语句就是比较常用的简单替换了,在预处理阶段,程序代码中出现Pi的地方都被替换为后面的3.14159。
2.带参数的宏替换
#define MAX(a, b) (a)>(b)?(a):(b)
这个就是带参数的宏替换了,在代码中使用MAX宏的时候,括号内部的参数会跟随到宏替换中。当然这个替换需要注意的地方就是记得为每个参数加上(),不然可能会产生边际效应。
3.字符替换符:#@
先看下面的这段代码:
#include <stdio.h>
#define PT_CHAR(x) printf("%c", #@x);
int main(void)
{
PT_CHAR(d);
return 0;
}
程序的输出为d。或许你会问,那直接将宏定义中的#@x用x替换掉不就可以了么,粗略的一看这样的说法确实是可以的,但是宏替换的时候PT_CHAR(d)编译器会认为d是一个传递的参数,既然d并非一个常量,那么编译器就只好认为它是一个变量了,但是这样的话问题就出来了,d并没有定义过!
4.字符串宏替换符:#
这个跟上面的有点类似了,比如下面的两行代码片段:
#define PT_STRING(x) printf("%s", #x)
PT_STRING(Hello!);
如果想要达到输出为Hello!的目的,就要使用#x,如果不使用的话根据前面的分析,编译器会把Hello!整体理解为一个变量,但是即便这样理解的话,这个!也是不能作为变量的一部分的啊,所以编译器会报出比较多的错误。
5.连接宏替换符:##
#define p(n) printf("symbol"#n"=%d", symbol##n)
int symbol9 = 9;
p(9);
上面的输出为symbol9=9,symbol##n将symbol和n(也就是传递过来的9)连接起来,构成了变量symbol9。
6.ANSI标准中的几个标准预定义宏
__LINE__:在源代码中插入当前源代码行号;
__FILE__:在源文件中插入当前源文件名;
__DATE__:在源文件中插入当前的编译日期
__TIME__:在源文件中插入当前编译时间;
__STDC__:当要求程序严格遵循ANSI C标准时该标识被赋值为1;
__cplusplus:当编写C++程序时该标识符被定义。
看到这里,上面的问题答案也就出来了,标准预定义宏中的__LINE__代表了源代码在改代码中的行号,使用这个宏就可以很方便的实现上面的功能了。
答案:#define PRINT_CLINE() printf("%d", __LINE__-4)
C语言中宏定义使用方法详解
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。