Assignment of union containing const-qualifier member

Alejandro Colomar alx@kernel.org
Sun Feb 4 20:37:38 GMT 2024


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.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://gcc.gnu.org/pipermail/gcc-help/attachments/20240204/a265f151/attachment.sig>


More information about the Gcc-help mailing list