#include<stdio.h>
#include<conio.h>
#define SQUARE(x) (x*x)
void main()
{
clrscr();
int i=3,j,k;
j=SQUARE(i++);
k=SQUARE(++i);
printf("\n%d\n%d\n%d",j,k,i);
getch();
}
Run Code Online (Sandbox Code Playgroud)
答案令人困惑:9 49 7我在想j = 3*4 = 12,k = 6*7 = 42,i = 7发生了什么事?我错过了什么吗?(x*x)=((x)*(x))这里相同.没关系.
这两行:
#define SQUARE(x) (x*x)
j=SQUARE(i++);
Run Code Online (Sandbox Code Playgroud)
翻译成:
j = (i++ * i++);
Run Code Online (Sandbox Code Playgroud)
这是未定义的行为.如果没有插入序列点(并且*不是序列点),则不允许两次修改变量.
你最好使用类似的东西:
inline int SQUARE (int x) { return x * x; }
Run Code Online (Sandbox Code Playgroud)
可能发生的是增量在乘法完成之后或之前一起发生,有效地为您提供:
i = 3; // i = 3
j = i * i; i++; i++; // j = 9, i = 5
++i; ++i; k = i * i; // i = 7, k = 49
Run Code Online (Sandbox Code Playgroud)
但请记住,这是在这种情况下发生的事情.由于您违反规则,实现可以自由地以其他方式执行.实际上,它可以根据需要格式化您的硬盘.这是未定义行为的本质,定义为(我的斜体):
在使用不可移植或错误的程序结构或错误数据时,本国际标准不对其施加任何要求.
注意可能的未定义行为包括完全忽略具有不可预测结果的情况,在转换或程序执行期间以环境特征(有或没有发出诊断消息)的特定文档执行,终止转换或执行(使用发布诊断消息).