可能重复:
谁能解释这些未定义的行为(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
之后将a1
和a2
设置为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 ++”是官方未定义的行为。
以上就是c/c++开发分享C编程#define?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/545672.html