2024/11/05

Newest at the top

2024-11-05 20:49:49 +0100 <probie> At least you can 100% safely use unions to convert between a signed int and an unsigned int of the same size
2024-11-05 20:48:20 +0100 <tomsmeding> what a crappy language
2024-11-05 20:48:04 +0100 <tomsmeding> (then again, I used 'int32_t', not 'int' -- searching for "int32_t" doesn't have any hits, so that code was implementation-dependent anyway)
2024-11-05 20:47:25 +0100 <tomsmeding> (the float value might have an object representation that is a trap representation for int)
2024-11-05 20:47:05 +0100 <tomsmeding> integer types can have trap representations according to the standard, so indeed probie: that union is not kosher!
2024-11-05 20:45:45 +0100 <tomsmeding> if you don't change the value, it's not a trap representation, and you're safe -- if I'm reading this correctly
2024-11-05 20:45:30 +0100 <tomsmeding> monochrom: so I guess one can memcpy() to an unsigned char[n], put that in a union together with the original type, and take the original type out
2024-11-05 20:45:03 +0100flounders(~flounders@2607:fb91:f6f:855:576:16c:1a7a:3eb2) flounders
2024-11-05 20:44:35 +0100 <tomsmeding> (found by <ctrl-F> "object repr")
2024-11-05 20:44:20 +0100 <tomsmeding> probie: footnote 99 on page 72 (pdfpage 59) in section 6.5.2.3 item 3 is relevant here ( https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2310.pdf )
2024-11-05 20:42:56 +0100flounders(~flounders@173.246.200.74) (Ping timeout: 252 seconds)
2024-11-05 20:42:32 +0100 <monochrom> "It is safe to copy your data to /dev/null" >:)
2024-11-05 20:42:06 +0100 <tomsmeding> and indeed it is funny that they don't say that "copying _from_ unsigned char[n]" is fine
2024-11-05 20:40:41 +0100 <monochrom> Programmers probably don't make great lawyers. :)
2024-11-05 20:39:58 +0100 <tomsmeding> monochrom: that "e.g." is tantalising
2024-11-05 20:38:26 +0100 <tomsmeding> probie: would that mean that memcpy() is the only defined way to look at the bits of a float value?
2024-11-05 20:38:25 +0100 <monochrom> Oh! Oops, 6.2.6.1 rule 4.
2024-11-05 20:37:55 +0100tomsmedingis too lazy to actually go search in the standard myself
2024-11-05 20:37:41 +0100 <probie> tomsmeding: I'm pretty sure that use of a union is also not kosher. I'm 90% sure that reading u.i after setting u.f is UB
2024-11-05 20:36:39 +0100L29Ah(~L29Ah@wikipedia/L29Ah) (Ping timeout: 260 seconds)
2024-11-05 20:36:31 +0100 <tomsmeding> monochrom: same https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2310.pdf (page 48, pdfpage 35)
2024-11-05 20:35:31 +0100 <monochrom> 2018
2024-11-05 20:35:25 +0100 <monochrom> OK OK nitpicking: It only says "copying to unsigned char[n] is OK", they probably forgot to say anything about "from". :)
2024-11-05 20:35:03 +0100 <tomsmeding> (of all things)
2024-11-05 20:34:59 +0100 <tomsmeding> monochrom: what standard version are you looking at? In my draft copy of C11, 6.2.6.2#4 is about bitwise operators applied to negative zero
2024-11-05 20:33:51 +0100Smiles(uid551636@id-551636.lymington.irccloud.com) (Quit: Connection closed for inactivity)
2024-11-05 20:33:46 +0100 <monochrom> By 6.2.6.2 item 4, you get much guarantees by using memcpy(&dst, &src, the_size).
2024-11-05 20:33:25 +0100 <dolio> There might be special cases where unions like that are defined to work. But not in general, I think.
2024-11-05 20:33:20 +0100 <tomsmeding> I know people are doing this precisely to evade the "pointer casting is not necessarily defined" thing
2024-11-05 20:33:04 +0100 <tomsmeding> dolio: oh isn't there? That would be funny
2024-11-05 20:32:53 +0100 <tomsmeding> er, *(int32_t*)&x
2024-11-05 20:32:38 +0100 <tomsmeding> int32_t float_to_int_wrong(float x) { return *(int*)&x; }
2024-11-05 20:32:26 +0100hamster(~ham@user/ham) (Read error: Connection reset by peer)
2024-11-05 20:32:25 +0100ham2(~ham@user/ham) ham
2024-11-05 20:32:21 +0100 <tomsmeding> as opposed to what naive C enthousiasts might write:
2024-11-05 20:32:04 +0100 <tomsmeding> int32_t float_to_int(float x) { union { int32_t i; float f; } u; u.f = x; return u.i; }
2024-11-05 20:31:39 +0100 <tomsmeding> no it's not a general casting trick, it is essentially c++'s reinterpret_cast
2024-11-05 20:31:23 +0100 <dolio> Also, I think there's no guarantee that writing to one field of a union and reading from a different field actually works.
2024-11-05 20:31:12 +0100target_i(~target_i@user/target-i/x-6023099) target_i
2024-11-05 20:31:01 +0100 <dolio> What is cast-through-a-union? I'd have to look, but I wouldn't necessarily expect a pointer to a union to be guaranteed to have the same address space as a pointer to either of its components.
2024-11-05 20:27:21 +0100zmt01(~zmt00@user/zmt00) (Ping timeout: 276 seconds)
2024-11-05 20:25:40 +0100 <tomsmeding> hence undefined signed integer overflow
2024-11-05 20:25:29 +0100 <tomsmeding> because that, supposedly, _is_ defined (or so I was told)
2024-11-05 20:25:29 +0100 <dolio> Or exact representations of all the integer types.
2024-11-05 20:25:14 +0100 <tomsmeding> hence the cast-through-a-union dance
2024-11-05 20:25:13 +0100emma-underscores(~underscor@pool-108-54-214-254.nycmny.fios.verizon.net) (Quit: WeeChat 4.4.3)
2024-11-05 20:24:42 +0100 <dolio> Yeah. There's no guarantee that differen't types inhabit the same memory, so things like casting between different pointer types isn't necessarily kosher.
2024-11-05 20:23:27 +0100swamp_(~zmt00@user/zmt00) zmt00
2024-11-05 20:23:20 +0100JuanDaugherty(~juan@user/JuanDaugherty) JuanDaugherty
2024-11-05 20:23:04 +0100 <tomsmeding> due to wanting to support platforms with very unusual (or historical) pointer representations, etc.