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

有一个错误。 在以下代码中为[i]赋值是不对的? 或条件运算符出了什么问题?

#include #include 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); 

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; 

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

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

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

通过遵循从条件表达一直到初级表达的可能性链,可以看出条件表达式可以是逻辑OR表达式 ,或逻辑AND表达式 ,或包含性OR。 – 表达式 ,或异或表达式 ,或AND表达式 ,或等式表达式 ,或关系表达式 ,或移位表达式 ,或加法表达式 ,或乘法表达式 ,或者 – 表达式 ,或一元表达式后缀表达式主表达式primary-expression标识符常量字符串文字(表达式)generics选择

因此, 赋值表达式可能是条件表达式)不在条件表达式的可能性列表中。 这就是问题中报告错误的原因:由于赋值表达式在此处不是有效语法,因此声明如下:

 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; 

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

但是,请注意,forms表达式 )的带括号的表达式有效的条件表达式赋值表达式表达式 。 所以,这是一份法律声明:

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

所有这些都说,这可能不是编码的正确方法。 最好使用其他答案中提出的替代方案之一,例如:

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

这有点棘手。 在C中有一个很好的概述“ 有效 ” 运算符优先级 ,我会引用那里的注释来解释你的问题*):

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

在DavidBowling在标准中的发现之后(感谢这项工作!),上面的第二段并不完全正确,或者至少有点令人困惑。 正确的是?:的右手操作数不能是赋值,但中间操作数可以。 因此,对于右侧, ?: “优先”超过= ,而不是中间部分。 任何部分都可以是主表达式 ,因此对“更改优先级 ”的禁止可以按预期工作:

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

但是,正如其他人所说,无论如何这都是不必要的复杂,你可以用你想要的东西来实现

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

这也更容易理解。


*)要理解此引文中的推理,您必须知道在C标准中使用左值来描述可能出现在分配的左侧 (因此名称)的内容(也可以分配给)。 这是一个有点草率的定义,并在C标准中进一步澄清,我认为这对于这个答案的背景是足够的。

在语句中使用=一次,因为它的优先级低于?: 。 就像是:

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