我无法理解以下c代码的执行情况

时间:2015-08-09 17:50:47

标签: c

#include <stdio.h>

#define sqr(a) a*a

int main()
{
    int i;

    printf("%d",64/sqr(4));

    return 0;
}

为什么我将输出设为64。

通常情况下,首先检查sqr(4)的值然后除以。如果是其他任何操作员,它可以正常工作。

请解释一下。

3 个答案:

答案 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++))