Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is `*--p` actually legal(well formed) in C++03

I'm wondering about this sample piece of code:

int main()
{
   char *p ;
   char arr[100] = "Hello";
   if ((p=arr)[0] == 'H') // do stuffs
}

Is this code actually well formed in C++03?

My argument is that the side effect of = is completed only after the next sequence point and since we are accessing the result of p=arr the code might not be well formed, there is no ordering between = and [] operations.

Am I correct?

The behavior is well defined in C and in C++11. This code is actually derived from MySQL.

like image 635
Prasoon Saurav Avatar asked Jan 13 '12 03:01

Prasoon Saurav


1 Answers

Of course it's well-defined.

It doesn't matter when the assignment p=arr takes place. You aren't evaluating p[0], you're subscripting the result of (p=arr), which is the pointer value which is being stored into p. Whether or not it's been stored yet doesn't change the value, and the value is known irrespective of whether p has been modified yet.

Similarly, in *--p, there's no undefined behavior. There'd only be undefined behavior if the same variable was accessed twice, including at least one write, between sequence points. But p is only accessed once, as part of --p. It isn't read again (*p), the dereferencing operator is applied to the result of --p which is a well-defined pointer value.

Now, this would be undefined behavior:

void* a;
void* p = &a;
reinterpret_cast<void**>(p = &p)[0] = 0;

as would

int *pi = new int[5];
int i = **&++pi;

It should be clear that the result of a preincrement is not a read unordered with the write, because to assert that there is a race is to assert that ++p can never be used as an rvalue, in which case it must stand alone between sequence points, and post-increment could be used instead. There would be no advantage to having both pre-increment and post-increment in the language.

like image 173
Ben Voigt Avatar answered Oct 05 '22 22:10

Ben Voigt