An argument against stdint.h

Fri, 18 Jan 2013 11:44:09 +0000

I've only been programming C for about 15 years, so for the vast majority of that time I've been using C99. And most of that time has been spent writing low-level code (operating systems, drivers, embedded systems). In these kind of systems you care a lot about the exact sizes of types, since memory and cache are important as so is mapping variables to memory mapped registers. For this reason having a standard way of declaring variables of a certain bitsize struck me as a pretty smart thing to do, so I've almost always used stdint.h on my projects. And in the rare cases where it wasn't available used some close equivalent. However, there is an argument to be made against using them (an extension of the general argument against typedefs). The core of the argument against is that it hides information from the programmer that is vital in constructing correct programs.

Let's start with some simple C code:

unsigned int a;
unsigned int b;

The question is, what is the type of the expression a + b. In this case, things are fairly straight-forward. The results expression has the type unsigned int.

Slightly trickier:

unsigned short a;
unsigned short b;

In this case due to integer promotion the operands are promoted to int and therefore the resulting expression is also of an type int. Integer promotion is a little obscure, but relatively well known. Most of the time this isn't really a problem because if you assigned the expression back to a variable of type unsigned short the effect will be the same. Of course if you assign it to an unsigned int, then you are going to be in trouble!

So nothing really new there. There is some obscurity, but with local knowledge (i.e: just looking at that bit of code), you can tell with complete accuracy wha The problem occurs when you have something like:

uint16_t a;
uint16_t b;

So, now what is the type of the expression a + b? The simple answer is it depends. The only way to know the answer to this question is if you know what the underlying type of uint16_t is. And this is a problem, because the correctness of your program depends on being able to answer that question correctly. The unfortunate result of this is that in an attempt to make code more portable across different platforms (i.e.: by not relying on the exact sizes of types), you end up in a situation where the correctness of your program still depends on the underlying platform, although now in a nasty obscure manner. Win!

Of course, most of the time this doesn't matter, but in the times where it does matter it is certainly a problem. Unfortunately, I don't have a good suggestion on how to avoid this problem, other than careful coding (and I really hate having to rely on careful coding just to essentially get type safety correct). If you've got a good suggestion please let me know in the comments.

Of course, I think I will still continue to use stdint.h despite these problems, however it is certainly something that C programmers should be aware of when using these types.

blog comments powered by Disqus