C 如果执行下面的代码,输出将为8;不过,我觉得应该是10。有人能解释一下这里发生了什么吗?
为什么这个输出是8,不是应该是10C 如果执行下面的代码,输出将为8;不过,我觉得应该是10。有人能解释一下这里发生了什么吗?,c,c-preprocessor,C,C Preprocessor,为什么这个输出是8,不是应该是10 #include <stdio.h> #define A 2 + 3 #define B 2 int main() { printf("Hello, World!\n"); printf("%d\n", A * B); return 0; } #包括 #定义2+3 #定义b2 int main() { printf(“你好,世界!\n”); printf(“%d\n”,A*B); 返回0; } #define预处理器指
#include <stdio.h>
#define A 2 + 3
#define B 2
int main()
{
printf("Hello, World!\n");
printf("%d\n", A * B);
return 0;
}
#包括
#定义2+3
#定义b2
int main()
{
printf(“你好,世界!\n”);
printf(“%d\n”,A*B);
返回0;
}
#define
预处理器指令只是文本替换A
和B
不是变量,因此您的printf
变成
printf("%d\n", 2 + 3 * 2);
也就是8,2*3等于6,加上2等于8
要解决此问题并获得10
,请在指令周围放置()
#define A (2 + 3)
#define B 2
这将导致您的printf
扩展到
printf("%d\n", (2 + 3) * 2);
要查看预处理器在编译之前是如何展开的,可以将-E
标志传递给gcc
或clang
但是,更好的解决方案是对这些常量使用const int
或enum
const int A = 2 + 3;
const int B = 2;
// or
enum { A = 2 + 3, B = 2 };
#define
预处理器指令只是文本替换A
和B
不是变量,因此您的printf
变成
printf("%d\n", 2 + 3 * 2);
也就是8,2*3等于6,加上2等于8
要解决此问题并获得10
,请在指令周围放置()
#define A (2 + 3)
#define B 2
这将导致您的printf
扩展到
printf("%d\n", (2 + 3) * 2);
要查看预处理器在编译之前是如何展开的,可以将-E
标志传递给gcc
或clang
但是,更好的解决方案是对这些常量使用const int
或enum
const int A = 2 + 3;
const int B = 2;
// or
enum { A = 2 + 3, B = 2 };
这就是为什么宏中的括号很重要 宏执行简单的文本替换。因此,在宏处理之后,您的代码如下所示:
int main()
{
printf("Hello, World!\n");
printf("%d\n", 3 + 9 * 2);
return 0;
}
因为乘法具有更高的优先级,所以乘法首先发生,因此结果为21
通过在宏中插入括号,可以减少惊喜:
#define A (3 + 9)
#define B (2)
这导致:
int main()
{
printf("Hello, World!\n");
printf("%d\n", (3 + 9) * (2));
return 0;
}
这将输出24。这就是为什么宏中的括号很重要 宏执行简单的文本替换。因此,在宏处理之后,您的代码如下所示:
int main()
{
printf("Hello, World!\n");
printf("%d\n", 3 + 9 * 2);
return 0;
}
因为乘法具有更高的优先级,所以乘法首先发生,因此结果为21
通过在宏中插入括号,可以减少惊喜:
#define A (3 + 9)
#define B (2)
这导致:
int main()
{
printf("Hello, World!\n");
printf("%d\n", (3 + 9) * (2));
return 0;
}
这将输出24。按照它执行的顺序,您正在执行9*2+3。我不确定你是如何得到这些数字的,因为它应该是21。按照它执行的顺序,你的是9*2+3。我不确定你是如何得到这些数字的,因为它应该是21。宏扩展为
printf(“%d\n”,3+9*2)因此,输出为21或8或10。宏扩展为printf(“%d\n”,3+9*2)因此,输出为21,也不是8,也不是10。宏扩展发生在预处理的第四阶段中:
执行预处理指令,宏调用展开,,并执行_Pragma一元运算符表达式。(…)
因此,每个宏将精确地扩展到其定义A
->3+9
和B
->2
结果printf(“%d\n”,3+9*2)代码>
现在,编译器的角色是从语法和语义上分析表达式,在编译期间,基于C语言的优先运算符,它的计算值可能会达到21
movl $.LC1, %edi //first argument of printf "%d\n"
movl $0, %eax // second argument of printf 21
call printf
宏扩展发生在预处理的第四阶段:
执行预处理指令,宏调用展开,,并执行_Pragma一元运算符表达式。(…)
因此,每个宏将精确地扩展到其定义A
->3+9
和B
->2
结果printf(“%d\n”,3+9*2)代码>
现在,编译器的角色是从语法和语义上分析表达式,在编译期间,基于C语言的优先运算符,它的计算值可能会达到21
movl $.LC1, %edi //first argument of printf "%d\n"
movl $0, %eax // second argument of printf 21
call printf
你知道宏是如何扩展的吗?如果交换A
和B
,你会感到惊讶。现在我明白了为什么在社交媒体上,他们会发布诸如“3+9*2的结果是什么?”之类的内容。所有内容都在这里:@Meninx-メネンックス 这只是对宏扩展的误解,我相信OP理解算术优先级。你知道宏是如何扩展的吗?如果交换a
和B
,你会感到惊讶……现在我明白了为什么在社交媒体上,他们会发布诸如“3+9*2的结果是什么?”之类的东西,一切都在这里:@Meninx-メネンックス 这只是对宏展开的误解,我相信OP理解算术优先。对不起,我意识到我的质疑是错误的,但我理解你的意思。Thanks@RyanHaining我的荣幸:)对不起,我意识到我问错了,但我明白你的意思。Thanks@RyanHaining我的荣幸:)