Page 2 of 2
Posted: Sun Apr 08, 2007 3:32 pm
by proxy
oh i know most compilers accept it and that it functional works correct, but the C and C++ standards actually say that the result of a cast my not be used as an lvalue, the correct way to do it (and will likely result in equally efficient code) is the use of a temp, is like this:
Code: Select all
/* some setup for example */
unsigned long x;
unsigned long *p = &x;
unsigned char *p2 = (unsigned char *)p;
*p2 = 0xff;
/* instead of *((unsigned char *)p) = 0xff; */
BTW: gcc 4.x will give you an error if treat a cast like an l-value..so it is no longer an "academic" matter.
proxy
Posted: Sun Apr 08, 2007 3:45 pm
by Tyler
Could you explain, why is it illegal if it is possible? What is the difference between an L Value and an R Value, i thought R Values where like numbers and strings, so i dont see how anything but an L Value could be cast...
Posted: Sun Apr 08, 2007 3:55 pm
by proxy
first of all, r-value basically means "valid on right hand side of an assignment", so, logically, an l-value means "valid on the left hand side of an assignment"
as for why do some compilers allow it even if it isn't technically legal.
Well, just about every compiler out there isn't 100% standards compliant, not only that, but it is possible to have a compliant compiler which allows code with undefined behavior (as in just about anything could happen). Classic example of this is the XOR integer swap trick...commonly written like this:
a ^= b ^= a ^= b;
this will in principle swap the integer values of a and b...but this code is not legal! it violates sequence point rules (having to do with multiple assignments in one statement).. a legal way to write it is like this:
a ^= b;
b ^= a;
a ^= b;
just about no compiler will even warn on this example, but still, it is allowed to do anything, heck, hypothetically it is allowed to crash your computer (though it would likely work just fine).
Really it boils down to the fact that as far as compilers go, they are not a good way to determine if something is technically correct.
For more info on the l-value cast thing:
http://c-faq.com/ptrs/castincr.html
proxy
Posted: Sun Apr 08, 2007 4:06 pm
by mystran
proxy wrote:
BTW: gcc 4.x will give you an error if treat a cast like an l-value..so it is no longer an "academic" matter.
Truly? That doesn't make any sense..
Posted: Sun Apr 08, 2007 4:13 pm
by Tyler
proxy wrote:first of all, r-value basically means "valid on right hand side of an assignment", so, logically, an l-value means "valid on the left hand side of an assignment"
as for why do some compilers allow it even if it isn't technically legal.
Well, just about every compiler out there isn't 100% standards compliant, not only that, but it is possible to have a compliant compiler which allows code with undefined behavior (as in just about anything could happen). Classic example of this is the XOR integer swap trick...commonly written like this:
a ^= b ^= a ^= b;
this will in principle swap the integer values of a and b...but this code is not legal! it violates sequence point rules (having to do with multiple assignments in one statement).. a legal way to write it is like this:
a ^= b;
b ^= a;
a ^= b;
just about no compiler will even warn on this example, but still, it is allowed to do anything, heck, hypothetically it is allowed to crash your computer (though it would likely work just fine).
Really it boils down to the fact that as far as compilers go, they are not a good way to determine if something is technically correct.
For more info on the l-value cast thing:
http://c-faq.com/ptrs/castincr.html
proxy
I still don't see "why" the casting code should be illegal... that is my point, what about it exactly was wrong.
Posted: Sun Apr 08, 2007 5:53 pm
by proxy
to mystran:
Yes really :-/. I agree that from a technical point of view there is no reason why a cast can't be an l-value. All I know is that section 6.5.4 in my copy of the C99 standard (and believe me, C89 agrees) explicitly says that a cast does not yield an l-value. So if your compiler accepts it, then your compiler is wrong (BTW, starting with gcc 3.4 this behavior is marked deprecated because of this as well)
to Tyler:
"why" is a good question, as I said, I don't see why from a technical standpoint it is illegal, but it certainly is. My guess is that the standards committee felt that since casting to begin with is considered potentially dangerous but necessary, or they would have just not had it!) that they would put constraints on the rules of usage in the name of more clear and concise code.
(edit) BTW: in c++ the rules are a slightly different, firstly, I see no mention of this rule when refering to the c++ style casts (static_cast<T>(o), reinterpret_cast<T>(o), const_cast<T>(o), and dynamic_cast<T>(o), but it does make mention of it for C style casting. namely that the result is an l-value if and only if the target type is a reference type, otherwise it is an r-value. So the rules are similar in c++, but not exactly the same.
proxy
Posted: Sun Apr 08, 2007 6:21 pm
by pcmattman
It's dereferencing a pointer made on the fly. It's exactly the same as
Code: Select all
unsigned char* fb = (unsigned char*) 0x000A0000;
*( fb + ( 200 + ( 6 * 320 ) ) ) = 0;
It's just more compact.
Edit: It's also the same as
Code: Select all
unsigned char* fb = (unsigned char*) ( 0x000A0000 + ( 200 + ( 6 * 320 ) ) );
*fb = 0x4;
Posted: Sun Apr 08, 2007 9:22 pm
by proxy
it was never a question of what the code was doing, I felt that was clear...the question about about the legality of the code.
The bottom line is that it is illegal use the result of a cast as an l-value according to the C standard (and is the case in most cases in C++ as well)
proxy