与宏扩张混淆

时间:2013-01-21 09:34:18

标签: objective-c c macros

  

可能重复:
  Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)
  What problems might the following macro bring to the application?

我编写了一个带有宏扩展的示例应用程序,用于在我的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

我对这个结果感到惊讶。我对这种宏观扩张感到有些困惑。

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

3 个答案:

答案 0 :(得分:6)

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

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

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

答案 1 :(得分:6)

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

#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 ;-)。更确切地说:编译器可以自由地假设不会调用未定义的行为,只需确保代码在“正常”情况下正常工作。在意外情况下会发生什么事情是任何人的赌注。

答案 2 :(得分:1)

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

   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