Link to home
Start Free TrialLog in
Avatar of riceman0
riceman0

asked on

L-Value question


I have a fundamental question about C syntax.  In my copy of MSVC++.NET,

int xx = 0;  // definition

(xx=3) = 4;  // compiles

xx=3=4;    // does not compile, left operand must be an L value

my question is why *don't* I get an Lvalue error on the previous line.  In no way did I expect "(xx=3)" to result in an L-value.  I understand it's an R-value (i.e., can be the source of another assignment), didn't expect an L-value (i.e., corresponds to a memory location and can be the target of another assignment).

Is the rule always that (A=B) results in an L-Value with the same memory location as A?  Is this consistent for all flavors/compilers of C, or is this a microsoft-ism.

I'm studying the C standard a little bit, so bonus points if you can reference the relevant content in the standard.  Thanks very much for any thoughts.
Avatar of milindsm
milindsm
Flag of India image

Read this,

http://msdn.microsoft.com/en-us/library/bkbs2cds%28VS.80%29.aspx

It clearly says, "An l-value expression in parentheses" can be a l-value
Avatar of riceman0
riceman0

ASKER


Thanks.  That verifies my observation, however that is microsoft literature, could theoretically still be a microsoftism (although I'd be surprised).  

And in fact it adds a little confusion, I'm not sure why the parentheses make a difference... x=3 should evaluate the same as (x=3), both or neither should be L-values or R-values, right?

Ideally, if someone could relate this to the C standard that would be great.  I've read this and totally missed this rule.  

http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf
Avatar of phoffric
The = binary operator has right to left associativity.
So,
xx=3=4;
when fully parenthesized becomes:
xx=(3=4);  // 3 is not an lvalue
SOLUTION
Avatar of milindsm
milindsm
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>> since result of an assignment is always a l-value
Where in the c-spec did you find this?
>> "An l-value expression in parentheses" can be a l-value
Although this comes from MS, it happens to be true. For example,
   char ptr[] = "hello world";
   ( ptr[3] ) = 'x';
I was a little surprised that (xx=3) = 4;  // compiles under Visual Studio 2008 Express
  (xx=3) = 4;  // does not compiles under cygwin
Error:
  lvalue.c:11: error: lvalue required as left operand of assignment

(xx=3) definitely will return the value of xx (which is 3), but I didn't expect it to return the address of xx.
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
It's happens that in if statements, one forgets to use the == equality operator, and accidentally uses the = assignment operator. In if statements like this
     if( c = returnedValue ) {...}
the program compiles and may appear to work for awhile (either because c is the same value as returnedValue , or the bug goes unnoticed).

In the below code, one might mean to say:
       if( ( c = f() ) == -99 ) {...}
which means assign c the return value of f(), and then see if this returned value is -99.

But typos and oversights occur; and the == is accidentally replaced with an = assignment operator as shown in code below.

In VS 2008 Express, the output is:
     c test is true; c = -99
But, luckily, in cygwin, we get the compiler error:
     lvalue.c:6: error: lvalue required as left operand of assignment
int f(void) { return 1; }
int main() {
   char c;
   if( ( c = f() ) = -99 ) {
      printf(" c test is true; c = %d\n", c);
   }
   else {
      printf(" c test is false; c = %d\n", c);
   }
}

Open in new window

>>It's happens that in if statements, one forgets to use the == equality operator, and accidentally uses the = assignment operator. In if statements like this
     if( c = returnedValue ) {...}


Which is why you might often see something like this:

    if(returnedValue == c) {...}

so that if one writes

    if(returnedValue = c) {...}


You'll hopefully get a compilation error ... of course, this does require that returnedValue (the semantics seems to suggest that this isn't the case) isn't a reference!
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>>  if(returnedValue = c) {...}
peetm: thanks for bringing that up. In fact, if returnedValue is a literal value, then in one project's coding standards (which were audited by both internal and external reviewers), we were required to use this form to prevent such compilable code from getting into executables.

But I never did understand why the same rule applied to other test operators such as >.
Yeah, Infinity08, I keep reusing old VS projects forgetting to start with a C project (i.e., one with .c source code extensions). Dang cockpit error! I'll probably remember to use pure C VS projects from now on. :)
>>But I never did understand why the same rule applied to other test operators such as >.

Me neither - seems like overkill and a probable *source* of problems, c.f. if(n > 10) vs. if(10 > n)
>>>> I keep reusing old VS projects forgetting to start with a C project
You must not start with a C project. I am using a C++ console project with a few cpp files and one .c file (normally deactivated). If activated the .c  was compiled with ANSI C compiler.
>>>>    if(returnedValue = c) {...}
>>>> You'll hopefully get a compilation error ...

Hopefully not, cause I sometimes use like

  if (ret = func())

or

 if ((ret = func()) != XYZ_ERR)

which would then fail for the same reason.

   

Fascinating.  Sorry to accept early.  (More often I'm yelled at for being late.)
>>Hopefully not, cause I ..


Yes, but you *know* that I meant having a constant on the lhs.
ok... I give up.... please take away my points....!!!!
>> ok... I give up.... please take away my points....!!!!
Not acceptable - giving up is not an option! IMO, this was subtle. I have been corrected many times. In fact, I wasn't aware of the C++ difference in semantics. We are Exchanging!
Hi,

In simple term, a lvalue means anything to whom we can assign a value. When compiler sees the expression
           (xx=3) = 4;  // compiles
it first evaluates the expression within (xx=3) since the precedence of () is more than =(after ()). In this epression xx is a lvalue and compiler assigns 3 to xx. Once 3 is assigned to xx, xx is now used as lvalue to 4 and now 4 is assigned to xx.

In expression xx=3=4, the compiler uses the associativity because of the same precedence of the = operator within the expression. The associativity of = operator is from right to left. So 3 = 4 is evaluated first. Here 3 is not a lvalue because we can't assign 4 to 3. Therefore compiler gives an error.
xx=3=4;  
@brijesh_iae : that would be true for C++, but not for C. This has already extensively been discussed above.