与宏扩张混淆

Mid*_* MP 2 c macros objective-c

可能重复:
任何人都可以解释这些未定义的行为(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 ) ;
}
Run Code Online (Sandbox Code Playgroud)

输出是:

Value of i++ = 9
Value of ++i = 49
Run Code Online (Sandbox Code Playgroud)

预期产量为:

 Value of i++ = 9
 Value of ++i = 25
Run Code Online (Sandbox Code Playgroud)

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

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

P.P*_*.P. 6

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

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

   j = ( i++ * i++ ) ;
   k = ( ++i * ++i ) ;
Run Code Online (Sandbox Code Playgroud)


Joa*_*son 6

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

#define SQUARE(x) ( x * x )
j = SQUARE( i++ ) ;
k = SQUARE( ++i ) ;
Run Code Online (Sandbox Code Playgroud)

将扩大到

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

k = (++i * ++i);     // Same as above
Run Code Online (Sandbox Code Playgroud)

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