条件运算符中的这个赋值有什么问题?

What is wrong with this assignment in a conditional operator?

出现错误。 下面代码中给a[i]赋值是不是错了? 或者条件运算符有问题?

#include<stdio.h>
#include<string.h>
int main(){
  char a[12]="sumit tyagi";
  int i=0;
  while(a[i]!='[=10=]'){ 
  a[i]>90 ? a[i]=a[i]-32 : a[i]=a[i]+32; //error in this line
  i++;
  } 
  printf("\n %s",a);

a[i]>90 ? a[i]=a[i]-32 : a[i]=a[i]+32;

不是被评估为

a[i]>90 ? (a[i]=a[i]-32) : (a[i]=a[i]+32);

因为 = 的优先级低于 ?:。在标准 C 中你不能像上面那样写它,尽管一些编译器允许它作为扩展。

您可以将其编写为更具可读性(和可移植性)

a[i] += a[i] > 90 ? -32 : +32;

这有点棘手。 “effectiveoperator precedence in C 有一个很好的概述,我将引用那里的注释来解释您的问题 *):

There is a part of the grammar that cannot be represented by a precedence table: an assignment-expression is not allowed as the right hand operand of a conditional operator, so e = a < d ? a++ : a = d is an expression that cannot be parsed, and therefore relative precedence of conditional and assignment operators cannot be described easily.
However, many C compilers use non-standard expression grammar where ?: is designated higher precedence than =, which parses that expression as e = ( ((a < d) ? (a++) : a) = d ), which then fails to compile due to semantic constraints: ?: is never lvalue and = requires a modifiable lvalue on the left.

根据 DavidBowling 在标准中的发现(感谢这项工作!),上面的第二段并不完全正确,或者至少有点令人困惑。 ?: 的右边操作数不能是赋值是正确的,但中间操作数可以。所以对于右侧,?: "takes precedence" 在 = 之上,而对于中间部分则不是。任何部分都可以是 主表达式 ,因此对 "change precedence" 的泛化按预期工作:

a[i]>90 ? a[i]=a[i]-32 : (a[i]=a[i]+32);

但是,正如其他人所说,无论如何这都是不必要的复杂,您只需

就可以实现您想要的
a[i] += a[i]>90 ? -32 : 32;

这样也比较容易理解


*) 要理解此引用中的推理,您必须知道 lvalue 在 C 标准中用于描述可能出现在 上的内容左侧(因此得名)赋值(又名可以分配给)。这是一个有点草率的定义,并在 C 标准中进一步阐明,我认为这对于这个答案的上下文已经足够了。

在您的语句中使用一次 =,因为它的优先级低于 ?:。类似于:

a[i] = a[i] > 90 ? a[i] - 32 : a[i] + 32;

这确实是理解 conditional operator 语法的问题。这在 C11 标准的 §6.5.15 中有详细说明:

conditional-expression:
logical-OR-expression
logical-OR-expression ? expression : conditional-expression

因此,条件运算符的第三个操作数必须是条件表达式。通过标准中定义的语法跟踪条件表达式的可能性,发现赋值表达式不是选项之一。相关语法定义见§6.5 Expressions.

沿着从条件表达式一直回到主要表达式的可能性链,可以看出条件表达式可以是逻辑或表达式,或逻辑与表达式,或包含或表达式,或异或表达式,或与表达式,或等式表达式,或关系表达式,或移位表达式,或加法表达式,或乘法表达式,或强制转换表达式,或一元表达式,或后缀表达式,或主表达式主表达式是一个标识符,一个常量,一个字符串文字( 表达式 ) 通用选择 .

因此,assignment-expression可能是条件表达式)不在条件表达式的可能性列表中。这就是问题中报告错误的原因:由于赋值表达式在这里不是有效语法,语句:

a[i]>90 ? a[i]=a[i]-32 : a[i]=a[i]+32;

解释为:

(a[i]>90 ? a[i]=a[i]-32 : a[i]) = a[i]+32;

上述赋值表达式的左侧不是赋值表达式所需的可修改左值,因此会出现错误。

但是,请注意 ( expression ) 形式的括号表达式是 有效的条件表达式,而赋值表达式是一个表达式。所以,这是一个合法的声明:

a[i]>90 ? a[i]=a[i]-32 : (a[i]=a[i]+32);

综上所述,这可能不是正确的编码方式。最好使用其他答案中提出的替代方案之一,例如:

a[i] += a[i] > 90 ? -32 : 32;