8
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.

Community
  • 1
  • 1
Gibbs
  • 21,904
  • 13
  • 74
  • 138
  • 6
    Hint, use parenthesis liberally when working with `?:`. – hyde Oct 29 '14 at 06:27
  • 2
    not "for security reasons" but because it doesn't make any sense. and no, using pointers does NOT magically make the ?: operator yield an lvalue. The returned pointers are still temporary copies of one expression or another. what you could do is `*(*a > *b ? a : b) = 222`, with a and b being pointers. – The Paramagnetic Croissant Oct 29 '14 at 06:28
  • 1
    Thanks Hyde. I knew it how to overcome this. My doubt is why second code is invalid – Gibbs Oct 29 '14 at 06:28
  • Another hint: if you want to access memory, you need pointer to contain the address, and then you need to dereference the pointer by using `*`. – hyde Oct 29 '14 at 06:29
  • your code a>b?a:b=222; is equivalent to (a>b) ? a : (b=222); – nitish005 Oct 29 '14 at 06:38
  • @MichaelBurr: I have executed those both code, and both the way it is yielding same output – nitish005 Oct 29 '14 at 06:52
  • @user3801433 let me know the error that you got for the first code. – nitish005 Oct 29 '14 at 06:58
  • `0x123 = &a;` doesn't make any sense, can you describe what you are trying to do? – M.M Oct 29 '14 at 07:30
  • @Matt please read my description. I am asking why second code segment is invalid. And let me know the description i provided for both segments is right. – Gibbs Oct 29 '14 at 07:31
  • @user3801433 I am referring to your paragraph where you say tha tyou tried `0x123 = &a;` – M.M Oct 29 '14 at 07:32
  • @Matt, Yes. According to my assumption, second code segment returns value at that pointer. I assumed it's 0x123.[it's the address stored in that var] – Gibbs Oct 29 '14 at 07:34
  • @user3801433 you can't change numbers, that makes as much sense as trying `3 = 4;` – M.M Oct 29 '14 at 08:09
  • the syntax for the ?: operator is lvalue = (test condition)? true : false; the code contains: a>b?a:b=222; which is meaningless. – user3629249 Oct 29 '14 at 16:16

2 Answers2

12

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;
rici
  • 234,347
  • 28
  • 237
  • 341
  • no, it's not a syntax error. it's a semantic error. OP tries to assign **to the return value of the operator.** That doesn't work even with parentheses since it's an rvalue. – The Paramagnetic Croissant Oct 29 '14 at 06:29
  • Could you please explain what exactly the error is? – Gibbs Oct 29 '14 at 06:29
  • 3
    @TheParamagneticCroissant: It never gets to the semantic error because of the syntax error. (But it's true that if you fix the syntax error, you have to deal with the semantic error.) – rici Oct 29 '14 at 06:30
  • 1
    @user3801433 the ?: operator returns an rvalue. That's an unnamed temporary which designates no storage. it cannot possibly be assigned to because it doesn't make sense. again, pointers are not magic. Pointers are just normal values as everything else. If you return a pointer, then you can't assign to the returned temporary. You can, however, retrurn a copy of either of the pointers, which points to the same location as its "prototype" (the variable of which it is a copy of) and that you can dereference to obtain a true lvalue, which in turn can be assigned to. – The Paramagnetic Croissant Oct 29 '14 at 06:31
  • @rici yes, but obviously this is what OP does not understand. – The Paramagnetic Croissant Oct 29 '14 at 06:34
  • Hi, this answer only explains me about my second code segment. I am still confused. U ppl are saying that it returns rvalue. To confirm my knowledge, i [read it](http://stackoverflow.com/questions/2038414/lvalue-and-rvalue). So r value can be changed. – Gibbs Oct 29 '14 at 06:55
  • @user3801433: This answer says its a syntax error, specifically: "C syntax doesn't allow a ?: expression to be used on the left hand side of an assignment operator. " This answer and this answerer do not use the word "rvalue". – rici Oct 29 '14 at 07:10
  • @rici, your example returns *(&var) or *(0x1234). – Gibbs Oct 29 '14 at 07:29
  • @rici: instead of *(b>2 ? &a : &b) = 7; you can use ((b>2)? a : b) = 7; why you are making it complected. – nitish005 Oct 29 '14 at 08:47
  • 1
    @nitish005: That is ok in C++ but not in C. The question is tagged as C. – rici Oct 29 '14 at 13:21
-1
int a=2, b=22;
a>b?a:b=222;

I have run your above code in GCC version 4.8.1 it worked fine. Then I changed it to following that will clear your view.

#include <stdio.h>
main()
{
  int a=2, b=22;
  printf("answer: %d",a>b?a:b=222 );
}

it yields following output

answer: 222

a>b?a:b=222;

above line could be written as

(a>b)?a:(b=222);

when we run it 222 is assigned to variable b first and then ?: operator is executed.

nitish005
  • 106
  • 11
  • You are obviously compiling the program as C++. This question is about C, which has a different syntax. – rici Oct 30 '14 at 00:02