04 January 2022, 20:56 | #21 | |||
Registered User
Join Date: Jan 2021
Location: Germany
Posts: 18
|
Quote:
Quote:
If the union hack should really be legal, then there are some pretty tricky decisions. Why should Code:
union {int i;float f;} u; u.f=3.14; return u.i; Code:
int *pi=&u.i; float *pf=&u.f; *pf=3.14; return *pi; If not, we have a strange situation where - basically - *&u.i may be different from u.i. Apart from being a very ugly concept, there would be the need to specify exactly where the normal aliasing rules start and stop. This is more a question of what the compiler sees rather than a question of types. Specifying this formally probably requires introduction of some new concepts. Just have a look at the (non-)description of gcc's -fstrict-aliasing for the ugly consequences. AFAIK nothing like that has really been addressed in the C standard so far. If such a radical change was intended, I would expect much more than a hidden footnote. Quote:
|
|||
05 January 2022, 10:17 | #22 | |
bye
Join Date: Jun 2016
Location: Some / Where
Posts: 680
|
Quote:
What compiler yields different results for these? |
|
05 January 2022, 10:58 | #23 | ||
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,214
|
Quote:
Quote:
This problem you already have to some degree. A pointer to a member of an object can be aliased by a pointer to the object itself, i.e. you can change "struct {int i} s;" through *s.i and through (&s)->i. Last edited by Thomas Richter; 05 January 2022 at 11:05. |
||
05 January 2022, 10:58 | #24 |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,214
|
|
05 January 2022, 11:03 | #25 | |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,214
|
That is quite a while ago, and C evolved. I suggest to get an up-to-date version of the standard (from DIN, or from ISO, not the CD document, but the IS document), or to go to the moderated c newsgroup to check with some real experts there.
Quote:
|
|
05 January 2022, 11:14 | #26 |
Registered User
Join Date: Feb 2017
Location: Denmark
Posts: 1,098
|
Needs a little bit of indirection, but it's a classic strict aliasing violation: http://franke.ms/cex/z/T6T1EW |
05 January 2022, 12:19 | #27 | |
Registered User
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
|
Quote:
https://godbolt.org/z/v7d7nof18 |
|
05 January 2022, 12:27 | #28 | |||
Registered User
Join Date: Feb 2017
Location: Denmark
Posts: 1,098
|
I'm becoming more convinced that at best it's unclear whether type-punning via a union is allowed.
The GCC manual explicitly states: Quote:
Quote:
https://davmac.wordpress.com/2010/02/26/c99-revisited/ Rant by Linus Torvalds: https://lkml.org/lkml/2018/6/5/769 Edit: Quote:
Notice that it stops working if you do: printf("%d\n", *(int*)pi); Last edited by paraj; 05 January 2022 at 12:41. |
|||
05 January 2022, 14:13 | #29 | |
Registered User
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
|
Quote:
|
|
06 January 2022, 17:11 | #30 | ||||
Registered User
Join Date: Jan 2021
Location: Germany
Posts: 18
|
Quote:
Quote:
Quote:
Quote:
Basically the only use case for this hack is a kind of reinterpret-cast. However, this can already done by using a char-pointer. If there was a need to specify a better way to do that, the union hack is a really bad way. Apart from being inconsistent, it is neither efficient nor easy to write and it may break if someone does seemingly harmless changes to the code like using a pointer to the union. |
||||
09 January 2022, 13:29 | #31 |
bye
Join Date: Jun 2016
Location: Some / Where
Posts: 680
|
Well, unions are a good thing to do those reinterpret casts. And they are safe for direct use:
set union members as needed read union members as needed It's the standard way in gcc and its libs, e.g. Code:
union _FP_UNION_S { SFtype flt; struct _FP_STRUCT_LAYOUT { #if __BYTE_ORDER == __BIG_ENDIAN unsigned sign : 1; unsigned exp : _FP_EXPBITS_S; unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0); #else unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0); unsigned exp : _FP_EXPBITS_S; unsigned sign : 1; #endif } bits __attribute__ ((packed)); }; Code:
// a union to handle the union _d_bits { double d; struct { unsigned sign :1; unsigned exp :11; unsigned frac0 :20; unsigned frac1 :32; } b; unsigned u; }; And yes, some of the examples here will not produce the expected result, but no one <insert attributes> would use these unions in that bogus way. Plus since the code gets tested, all bugs get fixed^^ |
12 January 2022, 16:04 | #32 | |||
Registered User
Join Date: Jan 2021
Location: Germany
Posts: 18
|
Quote:
Quote:
Quote:
|
|||
13 January 2022, 16:39 | #33 | |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,214
|
Look, I'm not too much an expert of ANSI C pecularities, but I'm working with the language since quite a while with multiple compilers at multiple architectures. I believe it may be worth to investigate the issue at a somewhat more rigorous level than what can happen at this audience, but my personal experience is that this idiom is robust under multiple architectures and compilers, having checked at least gcc,icc,VS and clang.
Of course, the world of C is much larger than this, but for many practical matters, that's fine. Quote:
Thus, I would be quite resiliant to put it aside so quickly. It is in active use, and at least in my experience it has been shown to be quite portable, if not to be the most portable hack of possible hacks so solve the problem at hand. |
|
13 January 2022, 20:56 | #34 | |
Registered User
Join Date: Feb 2017
Location: Denmark
Posts: 1,098
|
Quote:
As I see it there are two separate issues: 1) is this type-punning using a union technically allowed by the C99 standard 2) is it a widely supported and often used practice (and assumed to be legal). The first point is a question for language lawyers that I agree won't be resolved here (though I'd be very interested in the discussion outcome). The second one I think is true (see e.g. netlib's dtoa for a classic example). A lot of useful source code relies on this behavior whether it's strictly allowed or not. It's a bit similar to the issue of single line comments in C89 (though the impact is obviously much greater for the compiler writer in this case). From an engineering perspective if I were relying on type-punning via unions, I'd stick with a know good version after verifying the (hopefully few) places where I relied on them and stick with a know-good version while lobby for a compiler change/flag. Testing out trivial versions I don't see vbcc generating anything that would break union type-punning BTW. Would be interesting to see one where it does break. |
|
29 January 2022, 13:33 | #35 |
Semi-Retired
Join Date: Mar 2012
Location: Leiden / The Netherlands
Posts: 1,993
|
To get back to my first posting. The following code:
Code:
void fetch_vertex_ff (void* driver, float *pointer) { WriteFloat(driver, pointer[0]); WriteFloat(driver, pointer[1]); } Code:
fmove.s (a5),fp0 lea 132(a4),a2 //(driver) fmove.s fp0,-(a7) move.l a4,-(a7) move.l (a2),a3 //(WriteFloat function) jsr (a3) move.l 4(a5),-(a7) //(now a direct store to stack instead of first to float) move.l (a4),-(a7) move.l (a2),a2 jsr (a2) |
29 January 2022, 17:18 | #36 |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,214
|
What's confusing here? The code is correct, just a bit more complicated than necessary. The single-move reads a single precision floating point of 4 bytes size, extends it to double precision, and then later rounds it back to single precision, and stores it on the stack.
|
30 January 2022, 20:12 | #37 | |
bye
Join Date: Jun 2016
Location: Some / Where
Posts: 680
|
Quote:
what compiler? if the function parameter is a float, no conversion is needed. Last edited by bebbo; 30 January 2022 at 20:33. |
|
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
VBCC - What's going on here? | deimos | Coders. C/C++ | 69 | 28 July 2018 16:14 |
Space Hulk (1993) - Question about ray casting & graphics | Cherno | Nostalgia & memories | 0 | 27 August 2017 10:24 |
Integers vs floats (FFP/Sing/Doub) + printf() | guy lateur | Coders. Asm / Hardware | 63 | 18 July 2017 17:57 |
Ray casting | sandruzzo | Coders. General | 14 | 21 June 2017 01:06 |
AmiDevCpp and Floats | AmigaEd | Coders. General | 0 | 18 January 2006 03:16 |
|
|