混淆宏扩展

可能重复:
谁能解释这些未定义的行为(i = i ++ + ++ i,i = i ++等…)
以下宏可能给应用程序带来哪些问题?

我编写了一个带有宏扩展的示例应用程序,用于在我的iOS(Objective C代码)中实现它。

它是这样的:

#define SQUARE(x) ( x * x ) main( ) { int i = 3, j, k ; j = SQUARE( i++ ) ; k = SQUARE( ++i ) ; printf ( "\nValue of i++ = %d\nValue of ++i = %d", j, k ) ; } 

输出是:

 Value of i++ = 9 Value of ++i = 49 

预期产量为:

  Value of i++ = 9 Value of ++i = 25 

我对这个结果感到惊讶。 我对这个宏扩展有点困惑。

为什么会这样? 请帮我找原因。

这实际上是未定义的行为(并且不应该依赖于另一个编译器甚至是同一个编译器的下一次运行),因为它在没有序列点的同一语句中增加了两次相同的变量,但这似乎在这里发生了案件;

 #define SQUARE(x) ( x * x ) j = SQUARE( i++ ) ; k = SQUARE( ++i ) ; 

将扩大到

 j = (i++ * i++); // Compiler could do i * i, then increment twice, or use i * (i + 1), or... k = (++i * ++i); // Same as above 

由于这是未定义的行为,编译器可以随意做任何事情(旧版本的gcc使程序启动nethack ;-)。 更确切地说:编译器可以自由地假设永远不会调用未定义的行为,只需确保代码在“正常”情况下正常工作。 意外情况下发生的事情是任何人的赌注。

您通过在没有插入序列点的情况下多次修改i来调用未定义的行为

在marco替换之后,这两行将如下所示:

  j = ( i++ * i++ ) ; k = ( ++i * ++i ) ; 

这是因为您在两个序列点之间将单个变量递增两次。 因此,这是一种未定义的行为

  int i = 3, j, k ; j = SQUARE( i++ ) ; // it becomes (i++ * i++) k = SQUARE( ++i ) ; // it becomes (++i * ++i) 

因此输出来的是未定义的。

你得到的输出是因为在第一次xpression之后我要增加两次所以在secon表达式中,由于预增量,i增加了两次,因此对于上面的增量,它也会增加两次。

 j=(i++ * i++)//it comes 3*3 k=(++i * ++i)// it comes 7 as two increments of above xpression