Most active commenters
  • renox(3)

←back to thread

The C23 edition of Modern C

(gustedt.wordpress.com)
397 points bwidlar | 17 comments | | HN request time: 0.001s | source | bottom
Show context
ralphc ◴[] No.41851601[source]
How does "Modern" C compare safety-wise to Rust or Zig?
replies(4): >>41852048 #>>41852113 #>>41852498 #>>41856856 #
1. renox ◴[] No.41852048[source]
You'd be surprised: Zig has one UB (Undefined Behaviour) that C doesn't have!

In release fast mode, unsigned overflow/underflow is undefined in Zig whereas in C it wraps.

:-)

Of course C has many UBs that Zig doesn't have, so C is far less safe than Zig, especially since you can use ReleaseSafe in Zig..

replies(2): >>41852363 #>>41852615 #
2. uecker ◴[] No.41852363[source]
UB is does not automatically make things unsafe. You can have a compiler that implements safe defaults for most UB, and then it is not unsafe.
replies(4): >>41852548 #>>41853004 #>>41853083 #>>41853762 #
3. ahoka ◴[] No.41852548[source]
By definition UB cannot be safe.
replies(2): >>41853174 #>>41854910 #
4. secondcoming ◴[] No.41852615[source]
Does C automatically wrap? I thought you need to pass `-fwrapv` to the compiler to ensure that.
replies(3): >>41852833 #>>41852848 #>>41852877 #
5. greyw ◴[] No.41852833[source]
Unsigned overflow wraps. Signed overflow is undefined behavior.
replies(1): >>41852909 #
6. renox ◴[] No.41852848[source]
-fwrapv is for signed integer overflow not unsigned.
replies(1): >>41853085 #
7. ◴[] No.41852877[source]
8. kbolino ◴[] No.41852909{3}[source]
This distinction does not exist in K&R 2/e which documents ANSI C aka C89, but maybe it was added in a later version of the language (or didn't make it into the book)? According to K&R, all overflow is undefined.
replies(1): >>41853245 #
9. duped ◴[] No.41853004[source]
That's implementation defined behavior, not undefined behavior. Undefined behavior explicitly refers to something the compiler does not provide a definition for, including "safe defaults."
replies(2): >>41853169 #>>41854616 #
10. ◴[] No.41853083[source]
11. sp1rit ◴[] No.41853085{3}[source]
Yes, as unsigned overflow is fine by default. AFAIK the issue was originally that there were still machines that used ones complement for describing negative integers instead of the now customary twos complement.
12. fuhsnn ◴[] No.41853169{3}[source]
Compilers are not prohibited to provide their own definition for UB, that's how UBsan exists.
13. marssaxman ◴[] No.41853174{3}[source]
this depends on your choice of definition for "safe"
14. wahern ◴[] No.41853245{4}[source]
I don't have my copy of K&R handy, but this distinction has existed since the initial codification. From C89:

  3.1.2.5 Types

  [...] A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting unsigned integer type.
Source: C89 (draft) at https://port70.net/~nsz/c/c89/c89-draft.txt
15. renox ◴[] No.41853762[source]
Well Zig has ReleaseSafe for this.. ReleaseFast is for using these UBs to generate the fastest code.
16. Maxatar ◴[] No.41854616{3}[source]
The C standard says, and I quote:

>Possible undefined behavior ranges from ignoring the situation completely with unpredictable results ... or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message)

So a compiler is absolutely welcome to make undefined behavior safe. In fact every compiler I know of, such as GCC, clang, MSVC has flags to make various undefined behavior safe, such as signed integer overflow, type punning, casting function pointers to void pointers.

The Linux kernel is notorious for leveraging undefined behavior in C for which GCC guarantees specific and well defined behavior.

It looks like there is also the notion of unspecified behavior, which gives compilers a choice about the behavior and does not require compilers to document that choice or even choose consistently.

And finally there is what you bring up, which is implementation defined behavior which is defined as a subset of unspecified behavior in which compilers must document the choice.

17. Maxatar ◴[] No.41854910{3}[source]
The definition given by the C standard allows for safe undefined behavior.