#include <stdio.h>
#define sqr(a) a*a
int main()
{
int i;
printf("%d",64/sqr(4));
return 0;
}
为什么我将输出设为64。
通常情况下,首先检查sqr(4)
的值然后除以。如果是其他任何操作员,它可以正常工作。
请解释一下。
答案 0 :(得分:6)
预处理后,printf行将是:
printf("%d",64/4*4);
这应解释为什么它打印64。
当宏定义包含表达式时,始终在宏定义中使用括号:
#define sqr(a) ((a)*(a))
即使这对于像sqr(x++)
这样的宏调用也不安全。所以不要使用marcos,除非你必须:)
答案 1 :(得分:0)
宏没有功能,他们(大多数)是愚蠢的文本替换。你的宏没有括号,所以当预处理器替换它时,你得到以下内容:
printf("%d",64/4*4);
由于/
和*
具有相同的优先级,这就像声明(64/4)*4
,当然是64
。
如果您希望sqr
宏安全地对其参数求平方,请将其包装在括号中:
#define sqr(a) (a*a)
答案 2 :(得分:0)
64/sqr(4)
已扩展为64/4*4
。
你必须对宏体进行括号化,并且还应该在括号中加上括号:
#define sqr(a) ((a)*(a))
收率:64/(4*4)
请注意,在实际编译开始之前,宏是由 C预处理器 执行的纯文本替换。
更好且类型安全的方法是使用inline
函数:
static inline int sqr(int a)
{
return a * a;
}
编译器可能会将内联插入到调用者代码中,就像宏一样。 OTOH,编译器可能决定不这样做,这取决于内部启发式。通常,您应该相信编译器使用正确的方法,除非您有严重的性能/代码大小问题。
这也可以防止两次评估参数a
。如果存在像
int i[2], *p = i;
sqr(*p++);
对于宏版本,这将导致未定义的行为(未定义的评估顺序):
((*p++) * (*p++))