Path: csiph.com!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail From: Tim Rentsch Newsgroups: comp.lang.c Subject: Re: Usage of union Date: Wed, 20 Jan 2021 07:03:20 -0800 Organization: A noiseless patient Spider Lines: 55 Message-ID: <86lfcnodl3.fsf@linuxsc.com> References: <0f20fca0-ccf0-4f43-99f7-d2ed20d9f3b7n@googlegroups.com> <12db7b19-3ba3-4562-aee9-51531a52fcf3n@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: reader02.eternal-september.org; posting-host="b1fd427021f152ca5ff6680f6ccee516"; logging-data="8211"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19iDIB+bEdbLMXef9KFDkFiS1q/h8uDNmY=" User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux) Cancel-Lock: sha1:Zrzh8zob3yDI3KPmsRKfN0Yjqm4= sha1:8NNoEtLGKXzAO4yN7/48amFD1jw= Xref: csiph.com comp.lang.c:158481 Lew Pitcher writes: > On Sun, 17 Jan 2021 08:41:29 -0800, wij wrote: > >> On Sunday, 17 January 2021 at 23:39:34 UTC+8, >> james...@alumni.caltech.edu wrote: >> ... >> >>> Note that, since the representation of types is not completely standard >>> specified for any type, and is entirely implementation-defined for many >>> types, there's virtually no portable way to take advantage of this >>> fact. >>> For example, there's no guarantee which bits of u16 are zeroed by >>> execution of u8[0] = 0. It could, for instance, be only the >>> odd-numbered bits (though that would require a VERY unusual >>> architecture). >> >> Understandable. But: > > For context, here's the relevant part of the OP: > > //----------------------------- > union { > uint16 u16; [understood to mean uint16_t] > uint8 u8[2]; [understood to mean uint8_t] > float flt; > } u; > > void t() { > u.u16=0; > > assert(u.u8[0]==0); > > >> 1. Will such a writing "assert(u.u8[0]==0);" cause UB? > > Yes. The prior code does not store a value in u.u8[0]; u.u8[0], > therefore, holds an indeterminate value. [...] This is wrong. The objects for u.u8[0] and u.u16 overlap. After assigning to u.u16, u.u8[0] holds the first 8 bits of the object representation of the value stored in u.u16. We know those bits must all be zero. We also know that the abstract value for the object representation (of u.u8[0]) of all bits zero will be 0. Thus the access is well defined and must yield the value 0, so the assert(u.u8[0]==0) must succeed. There is no undefined behavior, or even the possibility of undefined behavior. (Note the "understood to mean" annotations in the above quoted code. Different types could mean different conclusions.) The above statements apply to C, but not to C++. In C++ the rules for union members are different, and the access of u.u8[0] is undefined behavior, because it is being accessed outside of its lifetime.