this post was submitted on 21 Jan 2024
780 points (93.3% liked)

Programmer Humor

32380 readers
1438 users here now

Post funny things about programming here! (Or just rant about your favourite programming language.)

Rules:

founded 5 years ago
MODERATORS
 
you are viewing a single comment's thread
view the rest of the comments
[–] Ethanol@pawb.social 30 points 9 months ago (3 children)

But what if I want a union struct to quickly interpret floats as ints and vice versa! I need my C hacks!

[–] uis@lemmy.world 9 points 9 months ago (1 children)

You can't, C have strict aliasing.

[–] Jordan_U@lemmy.ml 4 points 9 months ago (1 children)

... Which compilers don't consistently enforce, much like most undefined behavior in C.

[–] uis@lemmy.world 2 points 9 months ago (1 children)

How to enforce undefined behavior?

[–] Jordan_U@lemmy.ml 1 points 9 months ago (2 children)

By refusing to compile any code that has undefined behavior. This is what rust's compiler does, and is simply not possible for a C compiler to do.

[–] uis@lemmy.world 2 points 9 months ago

Compiler knows what is undefined behaviour better than all lemmy experts

[–] Jordan_U@lemmy.ml 2 points 9 months ago (1 children)

To put it another way:

Strict aliasing is an invariant that C compilers assume you as a developer will not violate, and use that assumption to make optimization choices that, if you as the developer have failed to follow the strict aliasing rules, could lead to undefined behavior. So it's a variant that the compiler expects, but doesn't enforce at compile time.

I guess it is possible to just disable all such optimizations to get a C compiler that doesn't create UB just because strict aliasing rules were broken, but there are still many ways that you can trigger UB in C, while safe rust that compiles successfully theoretically has no UB at all.

[–] uis@lemmy.world 2 points 9 months ago (1 children)

Strict aliasing exists not for optimization, but for type alignment. You may need more space on stack to save uint32_t than uint8_t[5] because former has 32-bit alignment.

[–] Jordan_U@lemmy.ml 2 points 9 months ago

Either way, this is a rule that you as a human are required to follow, and if you fail the compiler is allowed to do anything, including killing your cat.

It's not a rule that the compiler enforces by failing to build code with undefined behavior.

That is a fundamental, and extremely important, difference between C and rust.

Also, C compilers do make optimization decisions by assuming that you as a human programmer have followed these strict aliasing rules.

https://gist.github.com/shafik/848ae25ee209f698763cffee272a58f8

Has a few examples where code runs "properly" without optimizations but "improperly" with optimizations.

I put "improperly" in quotes because the C spec says that a compiler can do whatever it wants if you as a human invoke undefined behavior. Safe rust does not have undefined behavior, because if you write code which would invoke UB, rustc will refuse to build it.

[–] anzich@feddit.de 1 points 9 months ago (1 children)

It's actually nonstandard. Use memcpy

[–] kevincox@lemmy.ml 1 points 9 months ago

Well it is standard. The standard says that it is undefined behaviour. But I guess you are right that some compilers have non-standard options to make it not undefined behaviour.

[–] jimbolauski@lemm.ee 1 points 9 months ago

Or if your pulling 4 byte data from an AtoD converter and it's ordered 2, 3, 0, 1 for a fixed point value that you need to convert to a standard float at an extremely high rate or else the ring buffer will fill and you'll start losing data.

That code review was a good time.