有人可以告诉我为什么这句话会出错 - Lvalue Required
(a>b?g=a:g=b);
但是这个是正确的
(a>b?g=a:(g=b));
其中a , b
和g
是整数变量,a
和b
被视为来自键盘的输入。
答案 0 :(得分:9)
在表达式中,
(a > b ? g = a : g = b);
关系运算符>
具有最高优先级,因此a > b
被分组为操作数。条件表达式运算符? :
具有次高优先级。它的第一个操作数是a>b
,第二个操作数是g = a
。但是,条件表达式运算符的最后一个操作数被认为是g
而不是g = b
,因为g
的出现更多地与条件表达式运算符绑定。它对赋值运算符。发生语法错误,因为= b
没有左侧操作数(l值)
您应该使用括号来防止此类错误,并生成更多可读代码,这些代码已在您的第二个语句中完成
(a > b ? g = a : (g = b));
g = b
的最后一个操作数: ?
具有l值g
,这就是为什么它是正确的。
或者你可以做
g = a > b ? a : b
答案 1 :(得分:8)
表达式:
(a>b?g=a:g=b)
解析为:
(a>b?g=a:g)=b
我们无法分配表达式,因此它的l值错误。
阅读:Conditional operator differences between C and C++ Charles Bailey的回答:
?:
的语法如下:
conditional-expression:
logical-OR-expression
logical-OR-expression ? expression : conditional-expression
这意味着a ? b : c = d
解析为(a ? b : c) = d
即使(由于“不是l值'规则”),也无法生成有效的表达式。
一个方注意:
请在表达式中保留空格,以便它变得可读。
(a>b?g=a:g=b);
应写成:
(a > b? g = a: g = b);
同样,您应该在;
和,
之后添加空格。
答案 2 :(得分:4)
问题是operator precedence:在C中,三元条件运算符(?:
)的优先级高于赋值运算符(=
)。
没有括号(这里没有做任何事情)你的表达式就是这样:
a > b ? g = a : g = b;
具有最高优先级的运算符将是比较>
,因此这是您获得第一个逻辑分组的位置:
(a > b) ? g = a : g = b;
下一个最高表达式是三元条件,它产生以下表达式:
((a > b) ? (g = a) : (g)) = b;
正如您所看到的,您现在最终会在赋值运算符的左侧使用左值(即值;而不是变量),这将无效。
正如您已经注意到的,解决方案是简单地将表达式分组。我甚至会考虑这种良好的做法,特别是如果你不确定你的优先权会如何发挥作用。如果您不想考虑它,请添加括号。只需记住代码可读性,如果可以,请自行解决运算符优先级,以确保一切正确且可读。
至于可读性:我可能在这里使用经典if()
或将赋值运算符移到三元条件之外,这通常是您定义max()
的方式:
g = a > b ? a : b;
或更通用的宏或内联函数:
#define max(a, b) ((a) > (b) ? (a) : (b))
inline int max(int a, int b) {
return a > b ? a : b;
}
答案 3 :(得分:1)
您的表达式(a>b?g=a:g=b)
被解析为:
(a>b?g=a:g)=b
// ^^^
conditional-expression:
logical-or-expression
logical-or-expression ? expression : conditional-expression
在C中,运算符?:
的运算符=
高precedence。然后,这意味着( a ? b : c = d )
将被解析为( a ? b : c ) = d
。由于l值的规则,第一个表达式也是有效的,但没有按照你的想法进行。
为避免此错误,您还可以:
g = ( a > b ) ? a : b;
答案 4 :(得分:1)
if(a>b)
{
g = a;
}
else
{
g = b;
}
可以替换为
g = a > b ? a : b; //if a>b use the first (a) else use the second (b)
答案 5 :(得分:1)
这个问题通常会触发一系列答案,试图通过运算符优先级的概念来解释这种情况。实际上,它无法用这种方式解释,因为这是输入的典型示例,其中诸如“运算符优先级”的代理概念被破坏。你可能知道,C语中确实没有“运算符优先级”。只有语法分组,通常不能通过运算符的任何线性排序来精确表达。
让我们来看看语言规范对它的看法。在这种情况下,C语法的相关部分是?:
运算符和=
运算符的语法。对于?:
运算符,它是
conditional-expression:
logical-OR-expression
logical-OR-expression ? expression : conditional-expression
并且=
运算符是
assignment-expression:
conditional-expression
unary-expression assignment-operator assignment-expression
在第一种情况下,关键部分是?:
运算符的最后一个操作数:它不是expression
,而是conditional-expression
。 conditional-expression
是C表达式语法的不同入口点:它在不再可能将=
运算符包含在{{1}中的位置“输入”语法}}。将conditional-expression
运算符“走私”到=
的唯一方法是将语法一直下降到最底层
conditional-expression
然后使用primary-expression:
identifier
constant
string-literal
( expression )
generic-selection
分支一直环绕到顶部。这意味着( expression )
只有在conditional-expression
明确包装时才能包含=
运算符。例如。语法禁止您将(...)
作为g = b
运算符的最后一个操作数。如果你想要这样的东西,你必须明确括起来:?:
。
第二段语法存在一种非常类似的情况:赋值运算符。赋值的左侧(LHS)是<smth> ? <smth> : (g = b)
。并且unary-expression
“输入”C表达式的一般语法,以便包含顶级unary-expression
运算符为时已晚。从?:
到达?:
运算符的唯一方法是一直下降到unary-expression
并取primary-expression
分支。这意味着语法禁止您将( expression )
作为a > b ? g = a : g
运算符的LHS操作数。如果你想要这样的东西,你必须明确地表达它:=
。
出于这个原因,“流行”的答案声称“运算符优先级”使语言将表达式解析为
(a > b ? g = a : g) = <smth>
实际上是完全错误的。实际上,正式C语法中没有派生树可以使您的输入符合C语言的语法。您的输入根本无法解析。这不是表达。它在语法上是无效的。 C语言将其视为语法乱码。
现在,在实践中,您可能会看到一些实现以“左值操作数需要左值”诊断消息进行响应。在形式上,这是一种误导性的诊断信息。由于上面的输入不满足C语言表达式的语法,因此没有“赋值”,没有“左操作数”,也没有有意义的“左值”要求。
为什么编译器会发出这条奇怪的消息?他们很可能确实将此输入解析为有效的C表达式
(a > b ? g = a : g) = b
(a > b ? g = a : g) = b
的结果绝不是C中的左值,因此是错误。但是,您对输入的这种解释是非标准(扩展?)行为,它在正式C语言中没有基础。特定实现的这种行为可能是由于他们尝试协调C和C ++语法(在这方面有很大差异),尝试生成更易读(尽管是“假”)错误消息或其他原因。 / p>
通常,在这样的实现中,在诸如
的输入的情况下也会弹出类似的问题?:
将发出相同的错误,建议使用a + b = 5
解析,而从迂腐的角度来看(a + b) = 5
根本不能解析为表达式(原因与上述相同)。 / p>
同样,正式地说,这还不足以说编译器“坏了”:编译器需要检测约束违规并发出某些诊断消息,这正是这里发生的事情。诊断消息的文本没有正确反映问题的本质这一事实是无关紧要的(编译器可以简单地说“哈哈哈!”)。但是,这种误导性诊断的一个不良后果是误导用户误解了问题,从这个问题的正式错误答案的抨击中可以明显看出BTW。