为什么在 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 中,++
的操作数必须是一个 左值 - 内存中的一个位置。 a
和 b
都是左值 - 但它们的总和不是,它是一个 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
,不允许其他操作
- 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
- 必须是实数:整数或浮点数,但不能是复数
- 或者可以是指针类型(但是空指针不行,因为它没有定义算术)
- 也可以是
_Atomic
或volatile
- 但它必须是一个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 + b
; a + b
将更改其存储值以供后续评估。
对increment的含义产生了混淆。在您的问题中,您应该在表达式 a + b
上加一,这可以描述为 计算 a
和 b
的总和并递增一个 。在 C 中,增量运算符 ++
具有非常特殊的语义:它会增加标量变量的值作为副作用,并根据它是放在所述变量之前还是之后计算增加的值或原始值.关于对象的类型,以及在同一表达式中其他地方使用同一对象,还有进一步的限制。
对于您的问题,解决方案是使用加法运算符添加 1
:a + b + 1
我正在尝试 运行 一部分代码并且不得不增加组合表达式的值 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 中,++
的操作数必须是一个 左值 - 内存中的一个位置。 a
和 b
都是左值 - 但它们的总和不是,它是一个 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
,不允许其他操作
- 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
- 必须是实数:整数或浮点数,但不能是复数
- 或者可以是指针类型(但是空指针不行,因为它没有定义算术)
- 也可以是
_Atomic
或volatile
- 但它必须是一个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 + b
; a + b
将更改其存储值以供后续评估。
对increment的含义产生了混淆。在您的问题中,您应该在表达式 a + b
上加一,这可以描述为 计算 a
和 b
的总和并递增一个 。在 C 中,增量运算符 ++
具有非常特殊的语义:它会增加标量变量的值作为副作用,并根据它是放在所述变量之前还是之后计算增加的值或原始值.关于对象的类型,以及在同一表达式中其他地方使用同一对象,还有进一步的限制。
对于您的问题,解决方案是使用加法运算符添加 1
:a + b + 1