1

This is related to JoGusto's answer at Casting Error: lvalue required as left operand of assignment. In the answer, he/she states:

but there is one case where it is not true: casting, then dereferencing a pointer:

*((int *) chrPtrValue) = some_integer_expression;

I think I found the answer at Joseph Mansfield answer from Why does an lvalue cast work?, where he cited the standard. But that confused me more because I can differentiate between lvalues and rvalues, but xvalues and prvalues are still new to me.

Naively, it seems to me that the rule is present for a reason, so some of the methods for circumventing it would probably be [indirectly or directly] illegal also.

I have a few questions related to the lvalue cast. The use cases includ the following. In the first case, the underlying types are different. In the second case, the qualifiers were changed.

float f;
*(static_cast<int*>(&f)) = 1;

int ptr = ...;
*(static_cast<volatile int*>(&ptr)) = NULL; 

Is it legal C and C++ circumvent the lvalue cast error using indirection then dereferencing?

If the cast only changes the qualifiers (i.e., static const or volatile) , then is it still legal in C and C++?

If its legal C and C++, then does it violate other rules, like GCC's aliasing rules?

Finally, if it does violate C or C++, or other rules, then what is the approved way to do it (perhaps a memcpy or memmove)?

Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885
  • There's no such thing as "C/C++", please pick one especially when talking about details like this. (And they're called aliasing rules, not anti-aliasing.) – Mat Aug 02 '15 at 05:03
  • Thanks Mat. Informally, I was speaking to the C family of languages. C/C++ was changed to C and C++. But I also work in Objective C, so if you have insight there, then it would be appreciated, too. (And I fixed the title... The older I get, the more I transpose characters and words...) – jww Aug 02 '15 at 05:15

2 Answers2

1

The JoGusto answer is (a) not very good, and (b) on a C question.

First, is it legal C and C++ circumvent the lvalue cast error like that (indirection then dereferencing)?

IDK what you mean by "circumvent the lvalue cast error". The code (T)x = y; is just illegal nonsense (except for the case in C++ where T is an lvalue reference, as Joseph Mansfield's answer covers). You don't circumvent it; you write code that has a sensible meaning and does what you want to do.

The code *(T *)ptr = y; compiles. It means to invoke the assignment operator on a T object which is stored at the address in ptr. It's the same as (T &)*ptr = y; in C++, which is reinterpret_cast<T&>(*ptr) = y; .

does it violate other rules, like GCC's anti-aliasing rules?

The behaviour is subject to alignment and strict aliasing. If there is not actually a T object stored at that address, nor an object of type compatible with T according to the list in the strict aliasing rule (in this case: int or unsigned int), then it is undefined behaviour.

then what is the approved way to do it (perhaps a memcpy or memmove)?

You could write:

int x = some_integer_expression;
memcpy(chrPtrValue, &x, sizeof x);

I can usually differentiate between lvalues and rvalues, and not xvalues and prvalues.

Which expressions are you having trouble identifying in this example?

M.M
  • 138,810
  • 21
  • 208
  • 365
  • *"Which expressions are you having trouble identifying"* - `xvalues` and `prvalues`. I took a compiler theory class in college (it was the most grueling class I took in college). We had `lvalues` and `rvalues`, but not the other types. (And college was years ago for me). – jww Aug 02 '15 at 05:46
  • *"... it depends on what object is stored at the location..."* - perfect; that's a segue into the next question I had. Does a cast to/from a type to a volatile type affect the ability to perform the cast using the trick above? I guess what I am asking here is, is it well defined even with modifiers? – jww Aug 02 '15 at 05:49
  • 1
    See [What are rvalues, lvalues, xvalues, glvalues, and prvalues?](http://stackoverflow.com/questions/3601602/what-are-rvalues-lvalues-xvalues-glvalues-and-prvalues) – M.M Aug 02 '15 at 05:57
  • 1
    @jww maybe http://stackoverflow.com/questions/2981827/ is relevant to your situation. The guy found he could 'trick' gcc out of aliasing optimization by using volatile (however it is still UB) – M.M Aug 02 '15 at 05:58
  • 1
    Yes it does not violate strict aliasing as one of the allowed types is "a cv-qualified version of the dynamic type of the object." As I alluded to earlier though, it probably doesn't solve whatever you were trying to solve. – M.M Aug 02 '15 at 06:59
  • @jww if you mean const or volatile, the term is *qualifiers*, or *cv-qualifiers* – M.M Aug 02 '15 at 07:20
  • *"You don't circumvent it; you write code that has a sensible meaning and does what you want to do."* - doesn't that mean you use a union to access the variables, then? (Or does C++ lack unions that don't violate UB, too) – jww Aug 02 '15 at 12:59
  • @jww `*(T *)ptr` is sensible, `(T)ptr` isn't, because `(T)*ptr` retrieves value from `*ptr`, converts it to `T` .. and how are you supposed to assign to this temporary value? – M.M Aug 02 '15 at 13:08
  • I don't disagree with you about `*ptr`. What I was wondering about was the `union`. – jww Aug 02 '15 at 13:41
  • It's not defined by the standard so it's usually considered to be UB – M.M Aug 02 '15 at 13:58
0

An "lvalue" cast is/was often used in writing compilers all the way up until 2010 or so. This loss of this extremely useful construct means that many legacy compilers such as pcom no longer compile in many environments.

Older versions of byacc -- perhaps as late as 1996 -- actually encouraged the use of this technique. If I remember correctly, the code in pcom used the technique extensively as did several pcc2-based compilers. (I know this from personal experience.)

dab
  • 1
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Sumit Sharma May 28 '22 at 16:59