Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my conditional operator giving me an error?

int a=2, b=22;
a>b?a:b=222;

This code is giving me an error. I think it's because the conditional operator returns the value of a or b based on the condition, so the value cannot be used as Lvalue. In my case, 22=222, so it's an error.

int *i, *j, a=2,b=222;
i = &a;
j = &b;
a>b?i:j=&a;

The compiler throws an error in this case also. According to my assumption, as in the previous case, here it returns a value of i or j. So 0x123 = &a; [let 0x123 is the address stored in j]. Isn't valid?

At this point, I made a search. And I tried 0x123 = &a;, but the compiler still throws an error. I guess the compiler will not allow me to modify memory locations for security reasons.

Please let me know all my assumptions are valid, and tell me what security error will occur if a programmer is allowed to manipulate memory locations. I assume that a memory location may contain a value that should not be modified.

EDIT The error is error: lvalue required as left operand of assignment.

like image 286
Gibbs Avatar asked Oct 29 '14 06:10

Gibbs


1 Answers

It's a syntax error. There's no problem using addresses:

#include <stdio.h>
int main() {
  int a=2,b=4;
  *(b>2 ? &a : &b) = 7;
  printf("a = %d; b = %d\n", a, b);
  return 0;
}

C syntax doesn't allow a ?: expression to be used on the left hand side of an assignment operator. The version above is syntactically correct, because the expression on the left-hand side of the assignment is a dereference expression with a parenthesized argument.

The only way to assign through a pointer is to use *ptr = val;. It doesn't matter how the pointer is computed, as long as it is a valid pointer to the type of the right-hand side. It could even be a constant -- but cast to a pointer --, if you had some way of knowing that the constant was a valid address: *(int*)(0x124) = 42;. But you always need the dereference operator to indicate that you are assigning through the pointer.


The detailed grammatical explanation:

There are two relevant grammatical productions which demonstrate the difference between C and C++ with respect to the original expression (' a>b?a:b=222`)

In C, we have (§§6.5.15-16): (emphasis added)


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

    assignment-expression:
        conditional-expression
        unary-expression assignment-operator assignment-expression

In C++, the equivalent productions (§§5.16-17): (emphasis added)


    conditional-expression:
        logical-or-expression
        logical-or-expression ? expression : assignment-expression

    assignment-expression:
        conditional-expression
        logical-or-expression assignment-operator initializer-clause
        throw-expression

Note that in C, the only thing that can come before an assignment operator is a unary-expression, so anything complex like a conditional-expression needs to be in parentheses. Also, the right-hand operand of a conditional-expression must be a conditional expression, which means that an assignment-expression is not valid.

In C++, by contrast, the assigned operand in an assignment-expression can be a logical-or-expression, which still means that a conditional-expression is not valid, but allows other possibilities (many of which are only useful if operators are overloaded). But a C++ conditional-expression can have an assignment-expression as its right-most operand.

So in C, a>b?a:b=222 is a syntax error. It cannot be produced by any production for expression. But in C++, the same expression is legal, and the right-most operand to the conditional operator is b=222; in other words, it is the same as a>b?a:(b=222).

It needs to be noted that just because an expression conforms to the syntax of the language does not mean that the expression is legal. The left-hand-side of an assignment operator must be a "modifiable lvalue". So none of the following syntactically correct expressions are legal:

int x;
-x = 3;  /* lhs is not an lvalue */

const int cx = 3;
cx = 4;  /* lhs is not modifiable */

In C++, this one might be legal if SomeType::operator!(int) returns a reference:

SomeType answer;
!answer = 42;
like image 107
rici Avatar answered Sep 18 '22 00:09

rici