osa1 github gitlab twitter cv rss

Fun C compile time assertion trick

December 30, 2013 - Tagged as: en, c.

It’s been long time since I wrote an interesting post but I still don’t have anything interesting and short enough for me to explain in a blog post. Anyway, here’s a fun C compile time assertion trick that I found in libSDL 2 codebase:

In C we have typedef which can be used for defining type synonyms. This code:

typedef int test;

Defines test as type synonym for int, and then you can replace ints in variable declarations with test.

Interestingly, you can also use illegal type names for typedefs, like this:

typedef int foo[10];

This is funny, because you can’t use foo[10] as type of a variable, so I don’t understand why this syntax is allowed. I think the reason is that a typedef is just like declaration and shares same syntax with it, so this is allowed. Still, this declaration looks pretty useless to me.

Anyway, apparently there are some other interesting uses of typedefs. This code:

typedef int foo[-1];

fails with:

test.c:13:17: error: 'foo' declared as an array with a negative size
typedef int foo[-1];

Furthermore, there are some expression-like C syntax that are actually evaluated at compile time1. For example:

typedef int foo[3-4];

Here 3-4 looks like an expression, but it’s actually evaluated at compile-time and thus this code fails with same error as above.

Using this two tricks, we can have some kind of compile-time assertions, like libSDL people use:

#define COMPILE_TIME_ASSERT(name, x) \
  typedef int dummy_ ## name[(x) * 2 - 1]

typedef uint16_t Uint16;

COMPILE_TIME_ASSERT(uint16, sizeof(Uint16) == 2);

This code checks in compile time if Uint16 really represents 2 bytes in memory and it fails to compile if it doesn’t. Interesting part here is that (x) * 2 - 1 expression evaluated at compile-time.2

  1. These are called constant expressions and specified in C11 standard(draft) section 6.6.↩︎

  2. Note that the x here will be already replaced with some other expression, passed with macro call.↩︎