2012-12-13 34 views
1

可能重复:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)左值问题

#include<stdio.h> 

int main() 
{ 
    char a[]="Hello"; 
    char *p=a; 
    while(*p) 
    ++*p++;  //Statement 2 
    printf("%s",a); 
    int x=10; 
    ++x++; //Statement 1 
    return 0; 
} 

当我编译此代码我在声明1,这我可以理解得到的左值所需错误。即使我打算做同样的事情,该声明2如何不会产生错误?有人可以放光吗?

+0

p在序列点之间被修改两次,所以这是未定义的行为。 – Lundin

+3

@Lundin不,它不是。 '++ * p ++'是'++(*(p ++))','p'只修改一次,没有UB。 –

+0

好吧,有一个问题:为什么你想写这样的代码,没有括号?使用正确的括号和行为将是可预测的+可读。 – anishsane

回答

0

从ISO C99标准报价:

6.5.2.4 Postfix increment and decrement operators 

Constraints
1
The operand of the postfix increment or decrement operator shall have qualified or unqualified real or pointer type and shall be a modifiable lvalue.

对于这种情况:

++*p++;  //Statement 2 

后缀++具有更高的优先级和前缀++*具有相同的优先级和right to left关联。这意味着它的第一步是增加指针而不是值。 所以它会给你的下一个地址type。然后value (which is actually *p)递增。所以,在这种情况下没有constraint violation。 与++(*(p++))相同。

对于低于其他情况下:

int x=10; 
++x++; //Statement 1 

在变量的上述情况下(未指针)++(任后缀或前缀增量或减量)给你rvalue,然后在rvalue施加++--constraint violation++--操作数应该是lvalue。见上面写的标准报价。因此给错误。

+0

Postfix ++的优先级高于一元*和前缀++。你似乎混淆了这一点。无论如何,这些代码都是未定义的行为,所以它没有任何目的试图弄清楚它会做什么。 – Lundin

+0

@Lundin:对于未定义的行为不太确定,但'++'和'*'具有相同的优先级...... – Omkant

+0

@Lundin:第2章'K&R'的C编程'2.12优先级和评估顺序'请参阅给定的运算符表。请问'++(*(p ++))'表达式的问题,请您解释一下吗? – Omkant

3

无法修改预增量和增量后产生的右值和右值。

因此++x++(语句1)显然是违反约束条件,编译器会给出错误。

但是对于声明2却不是这种情况。虽然p++产生的值不能修改,但可以是取消引用。或者,如果你这样做++p++这将相当于++x++的情况下,会给出一个错误。因为这里指针本身已被修改。

所以它相当于:++(*p++)

(请注意,括号仅用于理解,并不是必需的,表达式++*p++已定义明确。)

什么情况是:

  • 的后增量p++计算结果为p旧值,在这个例子中&a[0],和p存储的值增加。
  • *p++给出值p之前指向的增量,在本例中为a[0]
  • 最终的预增量增量值,所以a[0]变成I(可能是EBCDIC机器上的其他东西)。

当被存储的pa[0]递增后的值是不确定的,但是它们都必须已经被存储在下一序列点(端接;)。

+0

你有一个糟糕的表达方式,“后期增量引用了这个问题”。我知道你的意思是正确的,我不知道如何把它说得很好,但是那读错了。 (我喜欢预期改进的配方。) –

+0

@DanielFischer当我写它的时候,我感到有种感觉。不太确定如何重新说话。它看起来更好吗? –

+0

我试图更好地解释它,如果你不喜欢它,请回滚。 –

0
#include<stdio.h> 

int main() 
{ 
    char a[]="Hello"; 
    char *p=a; 
    while(*p) 
    ++*p++;  //Statement 2 
    printf("%s",a); 
    int x=10; 
    ++x=x++; //Statement 1 
    return 0; 
} 

//由于前后同时递增,此代码将获取相同的错误。 ,因为它不能同时分配和增加,它需要一个值来执行增量。