On Sun, Feb 04, 2024 at 07:40:23PM +0100, Alejandro Colomar wrote: > > It seems that a union only provides a view of the object. The union > > object doesn't automatically become const qualified if a member > > of the union is const-qualified. This seems to be the reason v.w = u.w > > works; otherwise, that modification can also be viewed as the > > modification of an object (v.r) defined with a const-qualified type through > > the use of an lvalue (v.w) with non-const-qualified type - something that's > > forbidden by the std. > > Modifying a union via a non-const member is fine in C, I believe. I > think you're creating a new object, and discarding the old one, so you > don't need to care if there was an old object defined via a > const-qualified type. That is, the following code is valid C, AFAIK: > > alx@debian:~/tmp$ cat u.c > union u { > int a; > const int b; > }; > > int > main(void) > { > union u u = {.b = 42}; > > u.a = 7; > return u.b; > } > alx@debian:~/tmp$ gcc-14 -Wall -Wextra u.c > alx@debian:~/tmp$ ./a.out ; echo $? > 7 > alx@debian:~/tmp$ clang-17 -Weverything u.c > alx@debian:~/tmp$ ./a.out ; echo $? > 7 Although I would have doubts about what happens if the union contains an aggregate, and you modify part of it: union u { int a[2]; const int b[2]; }; int main(void) { union u u = {.b = {42, 13}}; u.a[0] = 7; return u.b[0]; } or union u { struct { int a0; int a1; } a; const struct { const int b0; const int b1; } b; }; int main(void) { union u u = {.b = {42, 13}}; u.a.a0 = 7; return u.b.b0; } In these cases, we're mnodifying a const object (.b), via a non-const lvalue (.a.a0, and .a.a1). We're modifying it, because we keep the original value at .b.b1, but the new one at .b.b0, so in this case we can't say it's an entire new object. Is this legal? Both GCC and Clang accept it, but I have doubts. Maybe you could warn if the program sets a union via a const member when there are non-const members, because it seems like something wrong to do. But as long as you don't set the const member, you should be fine according to ISO C. That is, if you initialize the union via .a, then anything is valid, as the object is defined non-const. Have a lovely night, Alex -- <https://www.alejandro-colomar.es/> Looking for a remote C programming job at the moment.
Attachment:
signature.asc
Description: PGP signature