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.
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
The = binary operator has right to left associativity.
So,
xx=3=4;
when fully parenthesized becomes:
xx=(3=4); // 3 is not an lvalue
So,
xx=3=4;
when fully parenthesized becomes:
xx=(3=4); // 3 is not an lvalue
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
>> 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';
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.
(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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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
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);
}
}
>>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!
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
>> 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 >.
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)
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.
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.
>>>> 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.
ASKER
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.
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!
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;
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.
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