6

I have a piece of code in C given as follows :

main()
{
    int a=10, b;
    a>=5 ? b=100 : b=200 ;
    printf("%d" , b);
}

running the code on gcc compiler in unix generates the compile-time error as 'lvalue required as left operand of assignment' and points the error at b = 200 whereas in windows compiling using Turbo C gives 200 as output.

Can anybody please explain what exactly is happening in this case ?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
user3778845
  • 89
  • 1
  • 4
  • 6
    Use parentheses to clarify the operator precedence you want. (And don't use Turbo C. It's over 20 years old!) – Code-Apprentice Oct 19 '14 at 08:19
  • 1
    http://stackoverflow.com/questions/12068118/use-of-brackets-in-expression-that-include-ternary-operator – Laura Maftei Oct 19 '14 at 08:31
  • Does this answer your question? [Error: lvalue required in this simple C code? (Ternary with assignment?)](https://stackoverflow.com/questions/6966299/error-lvalue-required-in-this-simple-c-code-ternary-with-assignment) – Aconcagua Aug 09 '22 at 08:40

5 Answers5

16

In C the ternary operator is defined like

logical-OR-expression ? expression : conditional-expression

where conditional expression is defined like

logical-OR-expression

The assignment operator has a lower priority than the OR operator. Thus you have to write

a >= 5 ? b = 100 : ( b = 200 );

Otherwise the compiler consideres the expression like

( a >= 5 ? b = 100 :  b ) = 200;

As the result of the ternary operator in C is not an lvalue then the above expression is invalid and the compiler issues an error.

From the C Standard:

the result is the value of the second or third operand (whichever is evaluated), converted to the type described below

and footnote:

110) A conditional expression does not yield an lvalue.

Take into account that there is an essential difference between the operator definition in C and C++. In C++ it is defined as

logical-or-expression ? expression : assignment-expression

In C++ the same GCC compiles the code successfully

#include <iostream>

int main() 
{
    int a = 10, b;

    a >= 5 ? b = 100 : b = 200;

    std::cout << "b = " << b << std::endl;

    return 0;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Is it not the dup of that question? Did I close incorrectly with this?: http://stackoverflow.com/a/6966331/1275169 – P.P Oct 19 '14 at 09:04
  • @Blue Moon If I am not mistaken in these questions there are considered different parts of the operator. So I think they append each other. – Vlad from Moscow Oct 19 '14 at 09:06
  • AFAICS, it addresses the exactly the same problem. – P.P Oct 19 '14 at 09:08
  • @Blue Moon There is the same problem only in the sense that it is a problem with the ternary operator. But the operator has thre parts that deserve separate discussions. – Vlad from Moscow Oct 19 '14 at 09:16
  • This looks incorrect. Assignment in C is "unary-expression op assignment-expression". Therefore, "Otherwise the compiler consideres the expression like..." is incorrect. The compiler will just consider the expression as syntactical nonsense. Any sane error message like "lvalue required" is just QoI. – Johannes Schaub - litb Aug 15 '16 at 07:13
  • @JohannesSchaub-litb If you run this statement then the compiler will issue an error like "lvalue required as left operand of assignment". So there is nothing wrong in my answer. When the compiler meets the assignment operator it expects that the left operand is lvalue. So its parses the statement like ( a >= 5 ? b = 100 : b ) = 200; – Vlad from Moscow Aug 16 '16 at 15:58
  • Youhave written that the compiler considers the expression as "(...) = 200" which I interpret as meaning "according to C, the expression should be considered as (...) = 200", and this is what is wrong in the answer. Because it is not even an expression. The trailing "= 200" is unparsable. – Johannes Schaub - litb Aug 16 '16 at 17:30
  • And expectations don't guide parsing. Objective syntax and grammar rules do. – Johannes Schaub - litb Aug 16 '16 at 17:32
  • @JohannesSchaub-litb The compiler recognized the conditional operator starting to analyze the line from the left-most token. The error message I showed in my previous comment is about the language semantic. It is not about the language syntax. When the compiler met the assignment operator it issues the error message that the left operand that was recognized is not an lvalue. So there is nothing wrong in my answer. By the way you may down-vote correct answers without writing your wrong comments.:) – Vlad from Moscow Aug 17 '16 at 12:39
2

you can put it in braces for it to work.. like

(a>=5)?(b=100):(b=200);

and please assign a return type for your function main()

Haris
  • 12,120
  • 6
  • 43
  • 70
1

This error is caused by the syntax of the conditional-expression which is

logical-OR-expression ? expression : conditional-expression

Therefore, the part after : must be able to parse b = 200. However, conditional-expression cannot parse that, because an assignment expression has less precedence - you would need to put a parenthesis around the assignment expression

a>=5 ? b=100 : (b=200);

But the fact that you need a parenthesis here does not mean that the expression otherwise is parsed as (a>=5 ? b=100 : b) = 200, it is just a compiler's internal artefact that in the error message it talks about the left operand of assignment. The C language has the following two rules for the assignment expression syntax, and the rule that matches is applied

conditional_expression
unary_expression '=' assignment_expression

This interferes with recursive descent parsers, that would simply invoke parseConditionalExpression, and check what token follows. Therefore some C parser implementations choose to not give a syntax error here, but parse it as though the grammar said conditional_expression '=' ... above, and later when inspecting the parse tree, validate that the left hand side is an lvalue. For example, the Clang source code says

/// Note: we diverge from the C99 grammar when parsing the assignment-expression
/// production.  C99 specifies that the LHS of an assignment operator should be
/// parsed as a unary-expression, but consistency dictates that it be a
/// conditional-expession.  In practice, the important thing here is that the
/// LHS of an assignment has to be an l-value, which productions between
/// unary-expression and conditional-expression don't produce.  Because we want
/// consistency, we parse the LHS as a conditional-expression, then check for
/// l-value-ness in semantic analysis stages.

And the GCC parser's source code says

/* ...
In GNU C we accept any conditional expression on the LHS and
diagnose the invalid lvalue rather than producing a syntax
error. */
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
0

The parentheses should be around the condition in this case.

(a>=5) ? b=100 : b=200; should compile correctly

RE: K&R The C Programming Language (2nd):

Parentheses are not necessary around the first expression of a conditional expression, since the precedence of ?: is very low, just above assignment. (emphasis mine) They are advisable anyway, however, since they make the condition part of the expression easier to see.

faruk13
  • 1,276
  • 1
  • 16
  • 23
user50149
  • 1
  • 2
-7

Try this one! Because the ternary operator returns the value you have to assgin it to b!

#include <stdio.h>

main() {

    int a = 10, b;
    b = a >= 5 ? 100 : 200;
    printf("%d" , b);

}
Rizier123
  • 58,877
  • 16
  • 101
  • 156