我刚开始学习C而且我不确定一切是如何运作的。有些例子对我来说看起来很奇怪,我无法预测它会打印什么。我在GCC编程,我的意思是它是我的编译器,所以我测试的每个代码都在GCC中。
我理解指针等所有内容的工作原理,但也知道有宏。宏非常奇怪,我发现了一个我没有解释的例子。例如,请查看此代码特定代码:
s_client s_server s_time
它应该打印什么?好吧,我虽然很容易猜到,但现在我发现它并不容易。结果不是我想的那样。
这是我的推理:我们首先将s_server
定义为#include <stdio.h>
int main(void){
#define A 1
if(A == 0){
#define B 1
}
#ifdef B
printf("B is defined, which means that A == 0.\n");
#elif
printf("B isn't defined, which means that A == 1.\n");
#endif
printf("Value of A is %d\n", A);
return 0;
}
,然后A
为1
,然后将A
定义为0
}。因此,如果定义B
,则表示1
和其他B
。但是,令人惊讶的是它打印出来:
B被定义,这意味着A == 0 A的值是1
什么?它只是印出了一个矛盾。我不确定这在GCC中是否有些奇怪(因为我没有可视化工作室或其他编译器来测试它)。但是,我99%肯定我不知何故误解了宏。我尝试使用变量而不是宏,它可以正常工作。
这是一个问题,还是我只是误解了宏是如何工作的?请记住,我是C初学者,所以请放轻松:)。
提前谢谢。
答案 0 :(得分:4)
在实际编译代码之前,宏是预处理器的一部分。编译器将在代码中搜索所有预处理程序指令并相应地修改代码。因此,当编译器到达if(A == 0) {#define B 1}
时,它已经扩展到if(0 == 1) { }
。
宏可以轻松配置代码的一个方面或将幻数替换为有意义的定义。例如:
#define DO_HOUR_CALCULATION
#define NUMBER_OF_SECONDS_PER_MINUTE (60)
#define NUMBER_OF_SECONDS_PER_HOUR (NUMBER_OF_SECONDS_PER_MINUTE * 60)
...
#ifdef DO_HOUR_CALCULATION
int hours = time / NUMBER_OF_SECONDS_PER_HOUR;
int minutes = (time % NUMBER_OF_SECONDS_PER_HOUR) / NUMBER_OF_SECONDS_PER_MINUTE;
#endif // defined(DO_TIME_CALCULATION)
另一个用途是简化重复或可配置的任务:
#define DEBUG
#ifdef DEBUG
#define DPRINTF(fmt, args...) printf(fmt, ## args)
#else
#define DPRINTF(args...) do {} while (0)
#endif
...
ret = read(fd, p_buffer, buf_size);
DPRINTF("read(fd) returned %d\n", ret);
希望这有助于您和快乐的编码!
答案 1 :(得分:2)
在转换非预处理标记之前处理预处理指令。特别是,预处理指令总是在编译时评估,而不是在运行时(参见C标准,例如this draft)。 如果令牌是预处理令牌,则定义如下(所有其他令牌都是非预处理令牌):
6.10预处理指令
(2)预处理指令由一系列预处理组成 以#预处理标记开头的标记(在...开头) 转换阶段4)是源文件中的第一个字符 (可选地,在不包含换行符的空格之后)或 在包含至少一个换行符
的空格之后
所以if(A == 0)
是非预处理标记(因为相应的行不以#
开头,可选地前面有一些空格字符),而#define B 1
是预处理标记。
根据翻译阶段,预处理令牌在翻译时在其他令牌之前进行评估:
5.1.1.2翻译阶段
(4)执行预处理指令,宏调用 展开,并执行_Pragma一元运算符表达式。
(7)......由此产生的标记在语法和语义上都是如此 分析并翻译为翻译单位。
因此B
将在if(A==0)
翻译之前定义,特别是在if(A==0)
执行之前。因此,B
将始终在您的程序中定义。
答案 2 :(得分:1)
#define B 1
在运行时不会发生。它发生在编译时。所以#define B 1
是编译的一部分,无论A == 0
的结果如何,都是运行时比较
if(A == 0){
#define B 1
}
以下代码
#ifdef B
printf("B is defined, which means that A == 0.\n");
#elif
printf("B isn't defined, which means that A == 1.\n");
#endif
与
相同 printf("B is defined, which means that A == 0.\n");