条件运算符中的赋值有什么问题?
有一个错误。 在以下代码中为[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;