Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Eh, I hard disagree with this memo. He's either dismissing or unaware of the biggest advantage of unsigned types, namely they make invalid state unrepresentible. And essentially all of his criticism of unsigned types is really criticism of the sloppy way old C and C++ compilers let you mix signed and unsigned numbers in math operations.

Modern C/C++ compilers can and will warn you (quite aggressively) if you mix signed and unsigned numbers without thinking about it.

A lot of the examples also seem weird. Eg, he gives a negative example of a function:

    unsigned area(unsigned x, unsigned y) { return x * y; }
In this, he complains that you can still write buggy code:

    area(height1-height2, length1-length2);
He's right - that is potentially buggy, But, that code would be buggy whether the area function took signed or unsigned numbers as input. However, the signed version of this function is still worse imo because it could hide the logic bug for longer. If the area function should always return a positive number, I'd much rather that invalid input results in an area number like 4294967250 than a small negative number.

Similarly, accidentally passing a negative index to a vec is much more dangerous with signed indexes because v[-2] will probably quietly work (but corrupt memory). However, v[4294967294] will segfault on the problematic line of code. That'll be much easier to find & debug.

And a lot of the examples he gives, you'd get nice clear compiler warnings in most modern compilers if you use unsigned integers. You won't get any warnings with signed integers. Your program will just misbehave. And thats much worse. I'd rather an easy to find bug than a hard to find bug any day of the week.



The advantage of using signed types is that you can reliably find overflow bugs using UBSan and protect against exploiting such errors by trapping at run time. For unsigned types, wrap-around bugs are much harder to find and your program will silently misbehave.


With unsigned you can actually check for overflow yourself very easily

  z=x+y; if(z < x || z < y) // overflow
And bounds checks are just a single comparisons against an upper bound (handles both over and underflow)

  size = x + y;
  // or
  size = x - y

  if(size < bound) // good to go 
Prior to C23 (stdckdint.h) its very error prone to check for signed overflow since you have to rearrange equations to make sure no operation could ever possibly overflow.


You can write correct programs with both. The reality is that people often fail to do this. But you can automatically detect signed overflow and protect against it, while unsigned wrap detected at run-time could be a bug or could be just fine (e.g. because you did your own "overflow" check and handle it correctly). This makes it extremely hard to find unsigned wraparound bugs and impossible to trap at run-time.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: