C程序:输出似乎令人困惑

Joh*_*ohn 0 c

#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))这里相同.没关系.

pax*_*blo 8

这两行:

#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)

但请记住,这是在这种情况下发生的事情.由于您违反规则,实现可以自由地以其他方式执行.实际上,它可以根据需要格式化您的硬盘.这是未定义行为的本质,​​定义为(我的斜体):

在使用不可移植或错误的程序结构或错误数据时,本国际标准不对其施加任何要求.

注意可能的未定义行为包括完全忽略具有不可预测结果的情况,在转换或程序执行期间以环境特征(有或没有发出诊断消息)的特定文档执行,终止转换或执行(使用发布诊断消息).