Path: ...!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: bart Newsgroups: comp.lang.c Subject: Re: C89 "bug" Date: Sat, 14 Dec 2024 00:04:09 +0000 Organization: A noiseless patient Spider Lines: 68 Message-ID: References: <87jzc3v48r.fsf@nosuchdomain.example.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Injection-Date: Sat, 14 Dec 2024 01:04:09 +0100 (CET) Injection-Info: dont-email.me; posting-host="5c7cb80c878a222b5f2e823d5b5cc46b"; logging-data="3861589"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18wvpNdQ68Q2RFxp2MqB/2R" User-Agent: Mozilla Thunderbird Cancel-Lock: sha1:DRS58SJ0Vh2qKi1rO+VDGjIr2ho= Content-Language: en-GB In-Reply-To: Bytes: 3230 On 13/12/2024 18:51, David Brown wrote: > On 13/12/2024 19:24, Thiago Adams wrote: >> Em 12/13/2024 3:15 PM, Keith Thompson escreveu: >>> Thiago Adams writes: >>>> Does anyone knows how can I convert this code (external declaration) >>>> to C89? >>>> >>>> union U { >>>>      int i; >>>>      double d; >>>> }; >>>> >>>> union U  u = {.d=1.2}; >>>> >>>> The problem is that in C89 only the first member of the union is >>>> initialized. >>> >>> The obvious solution is: >>>      union U u; >>>      u.d = 1.2; >>> But that works only if u has automatic storage duration. >>> >>> You could also define a function that takes a double argument and >>> returns a union U result. >> >> Like this? >> union U { >>      int i; >>      double d; >> }; >> union U f(){ union U u; u.d = 1.2; return u;} >> union U u = f(); >> >> The problem is that f() is not a constant expression for external >> declarations. >> > > Can you use gcc extensions here, or are you looking for strict C89 > compliance? > > (To me, the "bug" is using C89 in the first place, but you have your > reasons for that.) > > Another option if you are generating code is to make your union : > > union U { >     struct { unsigned int lo; unsigned int hi; } raw; >     int i; >     double d; > }; > > and always initialise it with the underlying representation for the > values and types that you want.  (I believe you are generating the code, > so that should be practical even for floating point data.) > > However, that puts a dependency on the endianness and size of types. > It gets a bit tricky also if it includes initialised 64-bit pointers (you can't split those). And also if the fields are deliberately misaligned (so using an intptr_t array won't be enough). There are other issues as well, but this depends on how far the OP is going. For example, when the definition for the union is inside an imported third party header, so only the initialisation is inside the code being translated. But maybe those external types will be recreated so can be augmented.