2012-03-31 29 views
2

它应该将当前字符设置为下一个字符。例如:why * foo ++ = * ++ foo可能未定义?

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语法?

+1

首先在SO上搜索(“C序列点”将是一个好的开始)。错误消息说明了这一切(或大部分):一个对象不能在一个明确定义的方式中在同一个序列点中被修改两次。这就是C如何定义(或根据具体情况而定义不明确)。 – 2012-03-31 00:40:54

+0

我不是C程序员,但从外观上看,它看起来完全像错误所说的那样,'* foo'对它没有任何价值,即'undefined'。你不能添加某些不存在的东西。 – 2012-03-31 00:41:12

+0

你在循环内增加3次。当然,这是你想要的? – 2012-03-31 00:42:00

回答

4

让我们来看看这个表情仔细一看:

*foo++ = *++foo 

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

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

语言标准明确要求这一点,如未定义行为使编译器实现者可以自由地处理这种情况,他们认为合适的任何方式,没有要求尝试做“正确的事”(无论“正确的事“ 也许)。海湾合作委员会明显在这种情况下发布诊断,但他们不必。首先,并非所有情况都如此容易被发现。想象一下像

void bar (int *a, int *b) 
{ 
    *a++ = *++b; 
} 

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

+1

我认为这个例子需要固定来增加int而不是指针。 +1为一个很好的描述。 – ams 2012-03-31 13:11:23

6

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

相关问题