C编程#define?

可能重复:
谁能解释这些未定义的行为(i = i ++ + ++ i,i = i ++等…)

#include #include #define SQ(x) x*x void main() { int a1 , a2; int b1 , b2; a1 = 2; a2 = 2; b1 = 0; b2 = 0; b1 = SQ(a1++); b2 = SQ(++a2); printf("Frist = %d",b1); printf("Second = %d",b2); } 

我知道代码的输出是什么。

因为#define在其他程序中工作,所以它不能在上面的代码中工作为什么。?

在同一个变量上使用多个++运算符的表达式的结果在C中正式是一个未定义的行为

#define是预处理器的一条指令,用于通过扩展来逐字地替换每个宏的出现。 因此,代码中的相关行将传递给编译器:

 b1 = a1++ * a1++; b2 = ++a2 * ++a2; 

正如Seva所说,这些表达方式正式未定义; 但即使我们采取可以说是最明智的阅读,你仍然会得到b1 = 2 * 3;b2 = 3 * 4;a2之后将a1a2设置为4。

SQ的两种用法都会调用未定义的行为,因为它们每个序列点多次分配给a1和a2。 您不应将带有副作用的表达式(例如赋值或增量)传递给宏。

因为define只是替换了表达式。 所以你得到的结果是:

 b1 = (a1++)*(a1++); b2 = (++a2)*(++a2; 

所以,你得到两次双倍增量。 它导致未定义的行为。

恭喜! 您刚刚发现为什么在这种情况下使用宏是个坏主意 。 作为一般规则,如果无法使用函数完成某些操作,则只能创建宏。 在这种情况下, SQ可以很容易地实现为函数:

 int sq (int x) { return x * x; } 

将括号内的宏中的操作数换行:

 #define SQ(X) (X)*(X) 

另外,尽量不要在同一个赋值中使用x ++和x。 可能导致未定义的行为。

干杯!

线条

 b1 = SQ(a1++); b2 = SQ(++a2); 

扩展到

 b1 = a1++ * a1++; b2 = ++a2 * ++a2; 

调用未定义的行为(一个对象的序列点之间最多可以修改一次),这意味着任何结果都被认为是“正确的”。

这就是这些宏的问题; 你真的希望对参数进行一次评估,但由于扩展它会被评估两次。

用表达式调用它也有问题

 x = SQ(a + b); 

这将扩展到

 x = a + b * a + b; 

这可能不是你想要的。 为了保留运算符优先级,扩展应该包含在() ,例如

 #define SQ(x) (x) * (x) 

查看代码,因为它将由预处理器扩展:

 b1 = a1++ * a1++; b2 = ++a2 * ++a2; 

这是未定义的行为,因为您正在多次修改变量而它们之间没有序列点。

我真的不知道你的问题是什么,但也许你的预期输出有问题…请注意#define是一个“简单”的文本替换,它在你的代码编译之前运行。 这个文本替换不尊重范围或语法正确..它只是替换任何与你所说的匹配的东西。 在你的情况下,它不会真正形成“a ++”结果的平方,而是生成这个代码:b1 = a ++ * a ++;

如果你看一下: 关于C编程的问题你可以看到一些解释为什么“a ++ * a ++”是官方未定义的行为。