为什么* foo ++ = * ++ foo可能未定义?

时间:2012-03-31 00:38:44

标签: c pointers gcc

它应该将当前字符设置为下一个字符。例如:

while( *foo ) { 
 if(baa(*foo)) *foo++ = *++foo;
  foo++;
}

但我收到以下错误:

error: operation on ‘foo’ may be undefined [-Werror=sequence-point]
cc1: all warnings being treated as errors

任何人都能解释为什么吗?那是无效的C语法?

2 个答案:

答案 0 :(得分:6)

你在作业的两边递增foo,其间没有序列点。这是不允许的;你只能在序列点之间修改一次值。

答案 1 :(得分:4)

让我们仔细看看这个表达式:

*foo++ = *++foo

*foo++评估为*(foo++)(后缀++的优先级高于一元*);您获取foo的当前值并取消引用它,并将foo作为副作用提前。 *++foo评估为*(++foo)(一元*++具有相同的优先级,因此它们从左到右应用);取值foo + 1,取消引用结果,然后再次提前foo作为副作用。然后将第二个表达式的结果分配给第一个表达式。

问题是所有这些副作用的确切顺序(赋值,后增量和预增量)是未指定;编译器可以根据需要自由重新排序这些操作。因此,x++ = ++x形式的表达式将为不同的编译器或具有不同编译器设置的相同编译器或甚至基于周围代码提供不同的结果。

语言标准明确地将其称为未定义行为,以便编译器实现者可以自由地以他们认为合适的方式处理这种情况,而无需尝试做“正确的事情”(无论如何) “正确的事”可能是)。 GCC显然在这种情况下发布诊断,但他们没有必要。首先,并非所有情况都如此容易被发现。想象一下像

这样的函数
void bar (int *a, int *b)
{
  *a++ = *++b;
}

这是一个问题吗?仅当ab指向相同的事物时,但如果调用者位于单独的翻译单元中,则无法在编译时知道这一点。