Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 增量算子中的左值问题_C_Post Increment_Pre Increment - Fatal编程技术网

C 增量算子中的左值问题

C 增量算子中的左值问题,c,post-increment,pre-increment,C,Post Increment,Pre Increment,可能重复: #包括 int main() { 字符a[]=“你好”; char*p=a; 而(*p) ++*p++;//语句2 printf(“%s”,a); int x=10; ++x++;//语句1 返回0; } 当我编译这段代码时,我在语句1中得到一个l值必需的错误,我可以理解。为什么即使我打算做同样的事情,语句2也不会产生错误?有人能发光吗?引用ISO C99标准: 6.5.2.4 Postfix increment and decrement operators 约束条件 1 后

可能重复:

#包括
int main()
{
字符a[]=“你好”;
char*p=a;
而(*p)
++*p++;//语句2
printf(“%s”,a);
int x=10;
++x++;//语句1
返回0;
}

当我编译这段代码时,我在语句1中得到一个l值必需的错误,我可以理解。为什么即使我打算做同样的事情,语句2也不会产生错误?有人能发光吗?

引用ISO C99标准:

6.5.2.4 Postfix increment and decrement operators
约束条件
1
后缀递增或递减运算符的操作数应具有限定或 非限定实数或指针类型,应为可修改的左值。

在这种情况下:

++*p++;     //Statement 2
后缀
++
具有较高的优先级,前缀
++
*
具有相同的优先级和
从右到左的关联性。这意味着在第一步,它增加的是指针,而不是它的值。
因此,它将为您提供该
类型的下一个地址。然后增加
值(实际上是*p)
。因此,在这种情况下,没有约束冲突。 它与
++(*(p++)
相同

对于以下其他情况:

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

在上述变量(非指针)的情况下,
++
(后缀或前缀递增或递减)为您提供
rvalue
,然后在
rvalue
上应用
++
--
约束冲突
++
--
操作数应该是
lvalue
。请参阅上面的标准引用。因此给出了错误

增量前和增量后都会生成右值,右值不能修改

所以
++x++
(语句1)显然是违反了约束,编译器给出了错误

但声明2并非如此。虽然
p++
生成了一个不能修改其值的右值,但它可以被取消引用。或者,如果执行
++p++
操作,这将等同于
++x++
案例,并将给出一个错误。因为这里指针本身被修改了

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

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

发生的情况是:

  • 后增量
    p++
    计算为
    p
    的旧值,在本例中
    &a[0]
    ,并且
    p
    的存储值递增
  • *p++
    给出增量前指向的值
    p
    ,在本例中为
    a[0]
  • 最后的预增量增加该值,因此
    a[0]
    变为
    I
    (可能是EBCDIC机器上的其他内容)
存储
p
a[0]
的增量值时未指定,但这两个值必须都存储在下一个序列点(终止的
)。

包括
int main()
{
字符a[]=“你好”;
char*p=a;
而(*p)
++*p++;//语句2
printf(“%s”,a);
int x=10;
++x=x++;//语句1
返回0;
}
//由于同时进行前增量和后增量,此代码将获取相同的错误。
因为它不能同时赋值和递增,所以需要一个值来对其执行递增

p在序列点之间被修改两次,所以这是未定义的行为。@Lundin不,不是
++*p++
++(*(p++)
p
只修改一次,没有UB。好的,一个问题:为什么要编写这样一个没有括号的代码?使用合适的括号&行为将是可预测且可读的。@DanielFischer Oops我是说x++x++是未定义的行为。@Lundin如果它编译的话,确实是这样。后缀++的优先级高于一元*和前缀+。你似乎把这个弄糊涂了。不管怎样,代码是未定义的行为,因此,试图弄清楚它将做什么并没有任何意义。@Lundin:不太确定未定义的行为,但
++
*
具有相同的优先级…@Lundin:C编程由
K&R
在第2章
2.12优先级和求值顺序
中给出的运算符表。以及
++(*(p++)
表达式有问题,请解释一下好吗?有3种不同的运算符,后缀++、前缀++和一元数*。它们的优先级在C11 6.5/3中指定:
运算符和操作数的分组由语法
指示。这意味着,C标准第6.5章中的操作员出现顺序说明了操作员的优先级。后缀++出现在6.5.2中,因此它的优先级高于前缀++和一元数*,后两者出现在6.5.3中,具有相同的优先级,但彼此之间是从右向左计算的。
++(*(p++)
:p++是下一个地址,然后
*(p++)
将是该地址的值,然后
++(*(p++)
将为您提供递增的值。我是这样分析的,我错了吗?你有一个很糟糕的公式,“它被后增量解引用了”。我知道你的意思是正确的,我也不知道该怎么说,但那是错的。(我投了赞成票,期待一个更好的公式。)@DanielFischer当我写这篇文章时,我有一种感觉。我真的不知道该怎么说。它看起来更好吗?我已经试着解释得更好了,如果你一点都不喜欢,滚回去。@DanielFischer谢谢。看起来比我拥有的要清楚得多。没想到用通俗易懂的英语写表达式
++*p++
会这么难:)
 int x=10;
 ++x++; //Statement 1
#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;
}