【问题标题】:Why is my conditional operator giving me an error?为什么我的条件运算符给我一个错误?
【发布时间】:2025-12-21 21:45:06
【问题描述】:
int a=2, b=22;
a>b?a:b=222;

这段代码给了我一个错误。我认为是因为条件运算符根据条件返回ab的值,所以该值不能用作Lvalue。在我的例子中,22=222,所以这是一个错误。

int *i, *j, a=2,b=222;
i = &a;
j = &b;
a>b?i:j=&a;

在这种情况下编译器也会抛出错误。根据我的假设,和前一种情况一样,这里它返回一个值ij。所以 0x123 = &a; [令 0x123 为存储在 j 中的地址]。无效吗?

此时,我发了一个search。我尝试了0x123 = &a;,但编译器仍然抛出错误。我猜出于安全原因,编译器不允许我修改内存位置。

请让我知道我的所有假设都是有效的,并告诉我如果允许程序员操作内存位置会发生什么安全错误。我假设一个内存位置可能包含一个不应修改的值。

编辑 错误是error: lvalue required as left operand of assignment

【问题讨论】:

  • 提示,在使用?: 时,请随意使用括号。
  • 不是“出于安全原因”,而是因为它没有任何意义。不,使用指针不会神奇地使 ?: 运算符产生左值。返回的指针仍然是一个或另一个表达式的临时副本。你可以做的是*(*a > *b ? a : b) = 222,a 和 b 是指针。
  • 谢谢海德。我知道如何克服这一点。我的疑问是为什么第二个代码无效
  • 另外提示:如果要访问内存,需要指针包含地址,然后需要使用*解引用指针。
  • 你的代码 a>b?a:b=222;相当于 (a>b) 吗? a : (b=222);

标签: c conditional-operator


【解决方案1】:

这是一个语法错误。使用地址没有问题:

#include <stdio.h>
int main() {
  int a=2,b=4;
  *(b>2 ? &a : &b) = 7;
  printf("a = %d; b = %d\n", a, b);
  return 0;
}

C 语法不允许在赋值运算符的左侧使用?: 表达式。上面的版本在语法上是正确的,因为赋值左侧的表达式是一个带括号参数的解引用表达式。

通过指针赋值的唯一方法是使用*ptr = val;。指针的计算方式无关紧要,只要它是指向右侧类型的有效指针即可。它甚至可以是一个常量——但转换为一个指针——如果你有某种方式知道这个常量是一个有效的地址:*(int*)(0x124) = 42;。但是你总是需要解引用操作符来表明你是通过 指针来赋值的。


详细的语法解释:

有两个相关的语法产生式证明了 C 和 C++ 在原始表达式 ('a>b?a:b=222`) 方面的区别

在 C 中,我们有(§§6.5.15-16):(添加了重点)


    条件表达式:
        逻辑或表达式
        逻辑或表达式?表达式:条件表达式

    赋值表达式:
        条件表达式
        一元表达式 assignment-operator assignment-expression

在 C++ 中,等效产生式(第 5.16-17 节):(已添加重点)


    条件表达式:
        逻辑或表达式
        逻辑或表达式?表达式:赋值表达式

    赋值表达式:
        条件表达式
        逻辑或表达式 赋值运算符初始化子句
        抛出表达式

请注意,在 C 中,唯一可以出现在赋值运算符之前的是 unary-expression,所以像 conditional-expression 这样复杂的东西都需要放在括号。此外,conditional-expression 的右侧操作数必须是条件表达式,这意味着 assignment-expression 无效。

相比之下,在 C++ 中,assignment-expression 中的赋值操作数可以是 logical-or-expression,这仍然意味着 conditional-表达式 无效,但允许其他可能性(其中许多仅在运算符重载时才有用)。但是 C++ 条件表达式 可以assignment-expression 作为其最右边的操作数。

所以在 C 中,a&gt;b?a:b=222 是一个语法错误。它不能由expression 的任何产品生产。但是在C++中,同样的表达式是合法的,条件运算符最右边的操作数是b=222;也就是说,和a&gt;b?a:(b=222)一样。

需要注意的是,仅仅因为表达式符合语言的语法并不意味着该表达式是合法的。赋值运算符的左侧必须是“可修改的左值”。因此,以下语法正确的表达式都不合法:

int x;
-x = 3;  /* lhs is not an lvalue */

const int cx = 3;
cx = 4;  /* lhs is not modifiable */

在 C++ 中,如果 SomeType::operator!(int) 返回一个引用,这可能是合法的:

SomeType answer;
!answer = 42;

【讨论】:

  • 不,这不是语法错误。这是一个语义错误。 OP 尝试将 分配给运算符的返回值。 即使使用括号也不起作用,因为它是一个右值。
  • 你能解释一下究竟是什么错误吗?
  • @TheParamagneticCroissant:由于语法错误,它永远不会出现语义错误。 (但确实,如果你修复语法错误,你必须处理语义错误。)
  • @user3801433 ?: 运算符返回一个右值。这是一个未命名的临时文件,表示没有存储空间。它不可能被分配,因为它没有意义。再次,指针不是魔术。指针和其他所有东西一样只是正常值。如果你返回一个指针,那么你不能分配给返回的临时。但是,您可以返回任何一个指针的副本,它指向与其“原型”(它是其副本的变量)相同的位置,并且您可以取消引用以获得真正的左值,这反过来可以分配给。
  • @nitish005:在 C++ 中可以,但在 C 中不行。问题标记为 C。
【解决方案2】:
int a=2, b=22;
a>b?a:b=222;

我已经在 GCC 版本 4.8.1 中运行了您的上述代码 它工作得很好。 然后我将其更改为以下将清除您的视图。

#include <stdio.h>
main()
{
  int a=2, b=22;
  printf("answer: %d",a>b?a:b=222 );
}

它产生以下输出

答案:222

a>b?a:b=222;

上面一行可以写成

(a>b)?a:(b=222);

当我们运行它时,首先将 222 分配给变量 b,然后执行 ?: 运算符。

【讨论】:

  • 您显然将程序编译为 C++。这个问题是关于 C 的,它有不同的语法。
最近更新 更多