这个 C 代码的输出是 49 但有人能解释一下吗?
The output of this C code is 49 but can someone explain me how?
#include <stdio.h>
#define CUBE(x) (x * x * x)
int main() {
printf("%d", CUBE(4+5));
return 0;
}
阅读 Modern C, then the n1570 draft C standard, and the documentation of GCC and of GDB and of CPP. See also this C reference 网站。
从现有的开源项目中汲取灵感,例如在 github, or GNU software.
最近 GCC compiler, invoke it 为 gcc -Wall -Wextra -g
。还可以使用 -C -E
选项来获取预处理的表单。
您可能还对 GCC 的 statement-expr 扩展感兴趣。
您的 CUBE(4+5)
被宏扩展为 4+5*4+5*4+5
,根据 C operators.
的优先级计算为 4+(5*4)+(5*4)+5
考虑编写一个 static inline
函数,例如
static inline int cube(int x) { return x*x*x; }
或者如果你需要一个宏,至少
#define CUBE(X) ((X)*(X)*(X))
这对 CUBE(i++)
不太适用(使用 inline
函数时,cube(i++)
会执行您希望它执行的操作:递增 i
一次!) .
顺便说一句,你可以使用 GPP, or GNU m4, (or your own generator, or GNU bison) to generate some C code. As a rule of thumb, think with ASTs: when you generate C code, emit a lot of useless parenthesis, like e.g. in Chicken Scheme, SWIG, or in CAIA or in my manydl.c
您也可以使用 Clang static analyzer on your code (and maybe Frama-C).
如果你想添加数字然后发送到 CUBE
,你需要像 CUBE((4+5))
这样的输入。因为 CUBE(4+5)
基本上扩展为 4+5*4+5*4+5
,因为它将整个 4+5
设置为 x
。所以,4+5*4+5*4+5
= 4+20+20+5
因为先乘法然后加上它们会得到 49
.
像#define CUBE(x) ((x)*(x)*(x))
一样定义宏,它实际上首先对每个(x)
执行(4+5)
操作,然后执行*
操作。
另一种方法是在调用宏时使用 CUBE((4+5))
,它基本上是先将两个数字和 (4+5)
= 9
相加,然后再执行 CUBE(9)
,例如:
#include<stdio.h>
#define CUBE(x) (x * x * x)
int main( )
{
printf("%d", CUBE((4+5)));
return 0;
}
宏会将代码变为:
printf("%d", (4+5 * 4+5 * 4+5));
这实际上是:
printf("%d", 4 + (5*4) + (5*4) + 5); // 29
如果你想立方9
得到729
,你应该写CUBE((4+5))
.
C 预处理器将按字面意思用 x 的所有实例替换 4+5,从而产生以下代码:
i = 4+5*4+5*4+5;
(先乘后加)
下面是宏在编译过程中是如何扩展的:
printf("%d", (4+5 * 4+5 * 4+5));
因为 *
的优先级高于 +
,所以这个表达式被计算为 (4 + (5 * 4) + (5 * 4) + 5)
,生成 49
而不是预期的 729
。
为避免此类运算符优先级问题,所有宏参数以及表达式本身都必须在宏定义中加括号:
#define CUBE(x) ((x) * (x) * (x))
但是请注意,CUBE
的扩展会多次计算 x
,如果宏参数有副作用,例如 CUBE(i++)
.
,这就是一个问题
要避免所有这些问题,请使用一个函数并让编译器对其进行优化:
int cube(int x) {
return x * x * x;
}
您可以在此函数定义前添加 static inline
,但现代优化器仍会在没有此定义的情况下内联该函数。
#include <stdio.h>
#define CUBE(x) (x * x * x)
int main() {
printf("%d", CUBE(4+5));
return 0;
}
阅读 Modern C, then the n1570 draft C standard, and the documentation of GCC and of GDB and of CPP. See also this C reference 网站。
从现有的开源项目中汲取灵感,例如在 github, or GNU software.
最近 GCC compiler, invoke it 为 gcc -Wall -Wextra -g
。还可以使用 -C -E
选项来获取预处理的表单。
您可能还对 GCC 的 statement-expr 扩展感兴趣。
您的 CUBE(4+5)
被宏扩展为 4+5*4+5*4+5
,根据 C operators.
4+(5*4)+(5*4)+5
考虑编写一个 static inline
函数,例如
static inline int cube(int x) { return x*x*x; }
或者如果你需要一个宏,至少
#define CUBE(X) ((X)*(X)*(X))
这对 CUBE(i++)
不太适用(使用 inline
函数时,cube(i++)
会执行您希望它执行的操作:递增 i
一次!) .
顺便说一句,你可以使用 GPP, or GNU m4, (or your own generator, or GNU bison) to generate some C code. As a rule of thumb, think with ASTs: when you generate C code, emit a lot of useless parenthesis, like e.g. in Chicken Scheme, SWIG, or in CAIA or in my manydl.c
您也可以使用 Clang static analyzer on your code (and maybe Frama-C).
如果你想添加数字然后发送到 CUBE
,你需要像 CUBE((4+5))
这样的输入。因为 CUBE(4+5)
基本上扩展为 4+5*4+5*4+5
,因为它将整个 4+5
设置为 x
。所以,4+5*4+5*4+5
= 4+20+20+5
因为先乘法然后加上它们会得到 49
.
像#define CUBE(x) ((x)*(x)*(x))
一样定义宏,它实际上首先对每个(x)
执行(4+5)
操作,然后执行*
操作。
另一种方法是在调用宏时使用 CUBE((4+5))
,它基本上是先将两个数字和 (4+5)
= 9
相加,然后再执行 CUBE(9)
,例如:
#include<stdio.h>
#define CUBE(x) (x * x * x)
int main( )
{
printf("%d", CUBE((4+5)));
return 0;
}
宏会将代码变为:
printf("%d", (4+5 * 4+5 * 4+5));
这实际上是:
printf("%d", 4 + (5*4) + (5*4) + 5); // 29
如果你想立方9
得到729
,你应该写CUBE((4+5))
.
C 预处理器将按字面意思用 x 的所有实例替换 4+5,从而产生以下代码:
i = 4+5*4+5*4+5;
(先乘后加)
下面是宏在编译过程中是如何扩展的:
printf("%d", (4+5 * 4+5 * 4+5));
因为 *
的优先级高于 +
,所以这个表达式被计算为 (4 + (5 * 4) + (5 * 4) + 5)
,生成 49
而不是预期的 729
。
为避免此类运算符优先级问题,所有宏参数以及表达式本身都必须在宏定义中加括号:
#define CUBE(x) ((x) * (x) * (x))
但是请注意,CUBE
的扩展会多次计算 x
,如果宏参数有副作用,例如 CUBE(i++)
.
要避免所有这些问题,请使用一个函数并让编译器对其进行优化:
int cube(int x) {
return x * x * x;
}
您可以在此函数定义前添加 static inline
,但现代优化器仍会在没有此定义的情况下内联该函数。