为什么在 C 中不允许使用表达式 c=(a+b)++?

Why is the expression c=(a+b)++ not allowed in C?

我正在尝试 运行 一部分代码并且不得不增加组合表达式的值 a+b。为了做到这一点,我写了声明

c=(a+b)++

此语句出现以下错误-
"expression must be a modifiable value"

为什么我会收到此错误以及为什么递增 C 中不允许的表达式的值?

因为 ++ 运算符需要一个引用(左值),而不是一个值(右值)。

i++ 将 i 增加 1 并且 return i 在增加之前的值。

(a + b)++ 不能增加 (a + b) 的值,因为 (a + b) 实际上不是一个引用(在内存中,在哪里更新 a + b 的值)。

在 C 中,++ 的操作数必须是一个 左值 - 内存中的一个位置。 ab 都是左值 - 但它们的总和不是,它是一个 rvalue.

后增量运算符只能应用于左值,即可以出现在赋值运算符左侧的东西,最常见的是变量。

x++ 出现在表达式中时,它被计算为 x 并且 x 随后增加。例如 a = 2; b = 2 * (a++); 等同于 a = 2; b = 2 * a; a = a + 1;.

您的示例无法编译,因为无法为 a+b 赋值。更明确地说 c=(a+b)++ 等同于 c = (a + b); (a + b) = (a + b) + 1;,这是没有意义的。

一个容易记住的语句是

左值 - 左值

LValue 必须是容器。换句话说,一个内存位置可以存储一些东西并且不受限制 而且,变量是 C 中唯一可用的容器。

示例中(a + b)++

(a + b) 评估为某个值,但不一定是可以再次用于在其上操作的容器。

例如考虑这个

const int a=10; 
a = 5;

这里也会报类似的错误,虽然a这里是一个容器,但是没有用,因为它是一个constant,不允许其他操作

C11 6.5.3.1p1:

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

这意味着如果我们有一个结构something ++,那么something

  • 必须是实数:整数或浮点数,但不能是复数
  • 或者可以是指针类型(但是空指针不行,因为它没有定义算术)
  • 也可以是_Atomicvolatile
  • 但它必须是一个lvalue,即指定一个对象被增量
  • 修改
  • 并且左值必须是可修改的(例如它不能是 const 合格的)

表达式

a + b

不是左值表达式,它不指定对象。它是一个算术表达式;算术表达式的值不是左值。虽然您可以将该值加 1,但表达式的值不是要修改的对象。


但是,鉴于

int a, *b, c[5][6];
struct FOO { char *bar; } foo, *fooz;
double *funnyfunc(int x);

所有这些表达式都是可修改的标量左值:

a
*(b + 5)
c[1][4]
foo.bar
fooz->bar
funnyfunc(5)[42]

你可以向他们申请++


还有一个问题
c = (a + b) ++

post-increment 表达式的值是 before increment 的值,即即使 a + b 是可修改的,c没有价值 a + b + 1 但无论如何 a + ba + b 将更改其存储值以供后续评估。

increment的含义产生了混淆。在您的问题中,您应该在表达式 a + b 上加一,这可以描述为 计算 ab 的总和并递增一个 。在 C 中,增量运算符 ++ 具有非常特殊的语义:它会增加标量变量的值作为副作用,并根据它是放在所述变量之前还是之后计算增加的​​值或原始值.关于对象的类型,以及在同一表达式中其他地方使用同一对象,还有进一步的限制。

对于您的问题,解决方案是使用加法运算符添加 1a + b + 1