7

为什么下面代码 16 的答案是?任何人都可以解释这个程序的工作原理吗?

#define SQUARE(n) n*n
void main()
{
    int j;      
    j =16/SQUARE(2);

    printf("\n j=%d",j);
    getch();
}

如果我们编写如下相同的代码,那么答案是 4:

//the ans is 4 why?
#include<stdio.h>
#include<conio.h>

#define SQUARE(n) n*n

void main()
{
    int j;      
    j =16/(SQUARE(2));

    printf("\n j=%d",j);
    getch();
}
4

9 回答 9

16

预处理器只是替换文本,完全按照书面形式。

所以,宏调用SQUARE(2)变成字面意思2*2

在您的情况下,这意味着整个表达式变为16/2*2,由于C 的优先规则,其计算结果为 (16/2)*2,即 16。

宏应该总是用括号括起来,并且每个参数也要括起来。

如果我们这样做,我们会得到:

#define SQUARE(n)  ((n) * (n))

替换为16/((2) * (2)),其计算结果为 16/4,即 4。

每个参数周围的括号使事情像SQUARE(1+1)预期的那样工作,没有它们的调用16/SQUARE(1+1)会变成16/(1+1*1+1)which is 16/3,即根本不是你想要的。

于 2013-01-30T13:21:29.073 回答
3

您需要使用绝缘括号定义宏,如下所示:

 #define SQUARE(n) ((n)*(n))

除此以外

 j = 16/SQUARE(2);

扩展到

j = 16 / 2 * 2;   which is equivalent to (16 / 2) * 2

当你想要的是

j = 16 / (2 * 2);   
于 2013-01-30T13:18:07.777 回答
3

操作顺序。您的表达式正在评估为:

 j = 16 / 2 * 2

等于 16。使它:

#define SQUARE(n) (n*n) 

这将强制首先评估正方形。

于 2013-01-30T13:19:58.933 回答
3

1. 使用要用作表达式的宏时,应将整个宏体括起来。

这可以防止错误的扩展,例如:

#define SQUARE(x) x*x
-SQUARE(5,5)
// becomes -5 * 5

2. 如果宏参数是表达式,也应该用括号括起来。

这可以防止不同类型的问题:

#define SQUARE(x) x*x
SQUARE(5+2)
// becomes 5 + 2*5 + 2

因此正确的方法是这样写:

#define square(n) ((n)*(n))
-SQUARE(5+2)
// becomes -((5+2)*(5+2))

虽然不鼓励使用宏作为函数(猜猜为什么),所以请改用函数。例如:

inline double square(n) { return n*n; }
于 2013-01-30T13:21:10.033 回答
2

宏的扩展将如下所示:

  j = 16/SQUARE(2);
  j = 16/2*2;

等于:j = (16/2)*2;意味着j = 16;

和 :

 j = 16/(SQUARE(2));
 j = 16/(2*2);

等于:j = 16/4;意味着j = 4;

于 2013-01-30T13:19:26.073 回答
2

因为宏将扩展为:

j = 16/2*2;

预编译器不对扩展做任何处理。它将扩展的宏按原样放置在您的代码中。由于您没有为替换文本加上括号,因此它也不会在主代码中为您执行此操作。做了 :

#define SQUARE(n) ((n)*(n))
于 2013-01-30T13:19:58.963 回答
1

第一个示例被评估为:

16 / 2 * 2
(16 / 2) * 2
8 * 2
16

第二个例子被评估为:

16 / (2 * 2)
16 / 4
4

在预处理器语句中添加括号以控制操作顺序:

#define SQUARE(n) ((n)*(n))

((n)*(n)) 中的外括号确保在执行任何外部操作之前 n 是平方的。内括号 (n) 确保在将表达式传递给 SQUARE 的情况下正确评估 n,如下所示:

16 / SQUARE(2 * 2)
16 / ((2 * 2)*(2 * 2))
16 / (4 * 4)
16 / 16
1
于 2013-01-30T13:22:29.137 回答
0

你会得到

j =16/2*2; // (16 / 2) * 2 = 16
于 2013-01-30T13:20:16.500 回答
0
Its because Whenever macro name is used, it is replaced by the contents of the macro.its simple rule of working of macro.


Case 1 : result 16

        define SQUARE(n) n*n
        void main()
         {
            int j;      
            j =16/SQUARE(2);

          printf("\n j=%d",j);
          getch();
       }

its get expand as below


j =16/SQUARE(2); 

so in place of SQUARE(2) it will replace 2*2 because Macro is SQUARE(n) n*n

j = 16/2*2
j = (16/2)*2
j = 8*2
j =16



Case 2 : result 4



        define SQUARE(n) n*n

        void main()
       {
            int j;      
            j =16/(SQUARE(2));

          printf("\n j=%d",j);
          getch();
       }



its get expand as below


j =16/(SQUARE(2));

so in place of SQUARE(2) it will replace 2*2 because Macro is SQUARE(n) n*n

j = 16/(2*2)
j = 16/(4)
j = 4


Hope this will help
于 2013-01-30T15:44:34.313 回答