C 条件运算符中的此赋值有什么问题?

C 条件运算符中的此赋值有什么问题?,c,compiler-errors,variable-assignment,conditional-operator,lvalue,C,Compiler Errors,Variable Assignment,Conditional Operator,Lvalue,有一个错误。 在以下代码中为[i]赋值是否错误? 或者条件运算符有问题 #include<stdio.h> #include<string.h> int main(){ char a[12]="sumit tyagi"; int i=0; while(a[i]!='\0'){ a[i]>90 ? a[i]=a[i]-32 : a[i]=a[i]+32; //error in this line i++; } printf("\n %s

有一个错误。 在以下代码中为[i]赋值是否错误? 或者条件运算符有问题

#include<stdio.h>
#include<string.h>
int main(){
  char a[12]="sumit tyagi";
  int i=0;
  while(a[i]!='\0'){ 
  a[i]>90 ? a[i]=a[i]-32 : a[i]=a[i]+32; //error in this line
  i++;
  } 
  printf("\n %s",a);
#包括
#包括
int main(){
字符a[12]=“sumit tyagi”;
int i=0;
而(a[i]!='\0'{
a[i]>90?a[i]=a[i]-32:a[i]=a[i]+32;//此行出错
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中,尽管某些编译器允许将其作为扩展,但不能像上面那样编写它

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


这有点棘手。这里有一个很好的“有效”概述,我将引用其中的注释来解释您的问题*):

语法中有一部分不能用优先表表示:赋值表达式不允许作为条件运算符的右操作数,因此
e=a
是一个无法解析的表达式,因此无法描述条件运算符和赋值运算符的相对优先性很容易就搞定了。
然而,许多C编译器使用非标准表达式语法,其中
?:
的优先级高于
=
,后者将该表达式解析为
e=(((a
,由于语义约束而无法编译:
?:
永远不是左值,
=
需要左侧的可修改左值

根据DavidBowling在标准中的发现(感谢这项工作!),上面的第二段不是完全正确的,或者至少有点混乱。正确的是,
?:
的右操作数不能是赋值,但中间操作数可以。因此,对于右侧,
?:
“优先”over
=
,但它不适用于中间部分。任何部分都可以是主表达式,因此,将其调整为“更改优先级”效果与预期一致:

a[i]>90 ? a[i]=a[i]-32 : (a[i]=a[i]+32);
但是,正如其他人所说,这是不必要的复杂无论如何,你可以实现你想要的只是

a[i] += a[i]>90 ? -32 : 32;
这也更容易理解



*)要理解这篇引文中的推理,您必须知道,左值在C标准中用于描述可能出现在赋值(aka可赋值)左侧(即名称)的内容.这是一个有点草率的定义,在C标准中得到了进一步的澄清,我认为这对于这个答案的上下文来说已经足够了。

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


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

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

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

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

通过沿着从条件表达式到主表达式的一系列可能性,可以看出条件表达式可以是逻辑或表达式、逻辑与表达式、包含或表达式、异或表达式、与表达式、等式表达式或关系表达式session、shift表达式、加法表达式、乘法表达式、强制转换表达式、一元表达式、后缀表达式或主表达式。主表达式是标识符、常量、字符串文字、(表达式)或泛型选择

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

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);
被解释为:

(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;
a[i]>90 ? a[i]=a[i]-32 : (a[i]=a[i]+32);
尽管如此,这可能不是编写代码的正确方法。最好使用其他答案中提出的备选方案之一,例如:

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

运算符优先级可能有问题。您使用
?:
的方式有点奇怪。您最好使用普通的
ìf…否则…
语句
a[i]=a[i]>90?a[i]-32:a[i]+32;
不要滥用三元运算符。对理论计算和编译必然失败的原因进行了很好的分析:您注意到我不敢这样做。请向上投票。幸运的是,我找到了一个写得很好的源代码来引用其中的棘手部分;)由于语法的吸引力,已经向上投票了;但进一步的挖掘向我揭示了at
a[i]>90?(a[i]=a[i]-32):(a[i]=a[i]+32);
实际上是合法的。我添加了一个(希望是正确的)用相关细节回答。@DavidBowling乍一看肯定是正确的!我会仔细检查一下标准,这意味着cppreference.com确实遗漏了一些东西。这确实是正确的。我会尝试更新我的答案,使之正确,仍然使用cppreference.com引文…好吧,天哪,现在你知道了eft me hanging.:)它是故意错误还是只是在细化过程中意外犯下的错误?(编辑历史记录似乎是错误的。)