What is wrong with this assignment in a conditional operator?

天大地大妈咪最大 提交于 2019-12-30 11:07:22

问题


There is an error. Is it wrong to assign a value to a[i] in the following code? Or something is wrong with conditional operators?

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

回答1:


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

is not evaluated as

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

since = has lower precedence than ?:. In standard C you can't write it as above although some compilers allow it as an extension.

You could write it as the more readable (and portable)

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



回答2:


This is really a matter of understanding the syntax of the conditional operator. This is spelled out in §6.5.15 of the C11 Standard:

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

Thus, the third operand to the conditional operator must be a conditional-expression. Tracing the possibilities for conditional expressions through the grammar defined in the Standard, one finds that an assignment expression is not one of the options. The relevant syntax definitions are found in §6.5 Expressions.

By following the chain of possibilities from conditional-expression all the way back to primary-expression, it can be seen that a conditional-expression may be a logical-OR-expression, or a logical-AND-expression, or an inclusive-OR-expression, or an exclusive-OR-expression, or an AND-expression, or an equality-expression, or a relational-expression, or a shift-expression, or an additive-expression, or a multiplicative expression, or a cast-expression, or a unary-expression, or a postfix-expression, or a primary-expression. A primary-expression is an identifier, a constant, a string-literal, an ( expression ), or a generic-selection.

So, an assignment-expression (which may be a conditional expression) is not on the list of possibilities for a conditional expression. This is the reason for the error reported in the question: since an assignment expression is not valid syntax here, the statement:

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

is interpreted as:

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

The left side of the above assignment expression is not a modifiable lvalue, as required for an assignment expression, hence the error.

But, note that a parenthesized expression of the form ( expression ) is a valid conditional-expression, and an assignment-expression is an expression. So, this is a legal statement:

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

All of that said, this is probably not the right way to code this. Better to use one of the alternatives proposed in other answers, such as:

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



回答3:


This is a bit tricky. There's a nice overview of "effective" operator precedence in C and I'll cite the notes from there explaining your problem *):

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.

After DavidBowling's findings in the standard (thanks for this work!), the second paragraph above is not entirely correct, or, at least a bit confusing. It's correct that the right-hand operand of ?: cannot be an assignment, but the middle operand can. So for the right-hand side, the ?: "takes precedence" over =, while it doesn't for the middle part. Any part can be a primary expression, therefore paranthesizing to "change precedence" works as expected:

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

But, as others have stated, this is needlessly complex anyways, you can achieve what you want with just

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

which is also easier to understand.


*) To understand the reasoning in this citation, you have to know that lvalue is used in the C standard to describe something that might appear on the left hand side (hence the name) of an assignment (aka can be assigned to). This is a somewhat sloppy definition and is clarified further in the C standard, I think it's enough for the context of this answer.




回答4:


Use = once in your statement, since it has lower precedence over ?:. Something like:

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



来源:https://stackoverflow.com/questions/45348272/what-is-wrong-with-this-assignment-in-a-conditional-operator

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!