Why use explicit signedness over implicit.

· 2 min read · zhrexx

note: this post is mostly about char

Why explicit signedness?

When you use char you rely on what the implementor decides to use. On Linux x86 its signed, on others it can be unsigned.

While you can detect char signedness at compile-time using limits.h (checking if CHAR_MIN < 0), relying on it forces you to write conditional code for both signed and unsigned. Explicit signedness (unsigned char) removes this burden entirely, ensuring consistent behaviour everywhere without #if hell.

Also how all/many of us (ched C developas) know, unsigned is more useful in 99% of cases.

Why prefer unsigned char over signed char

  1. It has standardized overflow behaviour: if you intrested click here, and read §6.2.5/9.. Signed overflow is just UB.
  2. It can hold more useful information: positive numbers are used MUCH often than negative once (0–255 vs -128–127)
  3. In C you use unsigned more often: for example uint64_t, uint32_t, uint16_t, uint8_t, when YOU have last used int64_t for example?

How to handle functions that use -1 to indicate something


int ic = getchar();

if (ic == -1) {
}
unsigned char c = ic;
//...

Its ugly, but honestly that a issue in C itself, WHY THERE IS NO TYPE WHO CAN HOLD -1–…, ITS USEFUL AS FUCK!

Sometimes signed char is actually useful

signed char is not bad, but its use-cases are niche. It fits well into embedded systems (e.g. for sensor offsets), arithmetic where negative numbers are expected or could accure; or in legacy code bases. But for general byte manipulation unsigned char just wins in every possible way.

But my compiler throws warnings when using a unsigned char* where a char* is expected, what to do?

Firstly, only stupid compilers do this (e.g. gcc; read here suckless.org(scroll down a bit)). If this annoys you or you cant / or dont want to toggle -Wno-pointer-sign when compiling

Honestly, just cast; its simple but yeah it can annoy you, if thats the case

just put


#if defined(__clang__)
#pragma clang diagnostic ignored "-Wpointer-sign"
#elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wpointer-sign"
#endif

at the top of the file, where you get the warnings from

—— with love, by @zhrexx