I just invented a new (to me) abuse of the C preprocessor. From a Stack Overflow answer I just wrote:


My understanding is that you are defining a constant, using it later to size one or more arrays, and also want that constant to be a symbol, preferably without a messy namespace. (If it were a matter of exporting the size of a single array, I would instead suggest sizeof(array) / sizeof(*array) as missingno did.)

static const int ASIZE = 10;
#define ASIZE            10
int array[ASIZE];

Here, there is a variable with the desired value which will be in the object file, but the preprocessor macro shadows it with the value itself, so the array definition also succeeds.

However, you may find the need to duplicate the value expression ugly. Wouldn't it be nice if we could define the variable in terms of the macro?

static const int ASIZE =
#define ASIZE 10
                         ASIZE;
int array[ASIZE];

I'm not sure whether this is actually a better idea maintainability-wise than the above, but it works (and I couldn't get gcc to be offended by it) and it contains no duplication other than of the identifier. And it's amusing.


Previous C adventures: A dreadful thing

(I'm posting this because I have the feeling it is not as well known as it should be.)

If you're compiling a C program with GCC, unless you have a reason to do otherwise (such as compatibility with other compilers), use -std=c99 instead of -ansi. -ansi specifically chooses the older C90 standard.

Why should you use C99? I'm not one to give you a complete list of changes (this article seems to be decent for that), but my favorite features are:

  • Boolean and complex number types
  • Variable declarations may be freely intermixed with statements, and used in the first expression of a for loop
  • // line comments
  • Variable-length arrays
  • Inline structure initializers: foo((struct bar){...});
  • Using field names or array indexes in structure initializers: struct bar g = { .x = 0, .y = 9.81 };

Note that many of these are common extensions to C (which would be rejected by -ansi -pedantic, I believe), but C99 makes them standard. C99 also removes some archaic features/looseness so as to make it harder to accidentally write incorrect programs.

Toy GC

Wednesday, January 12th, 2011 13:15

For a project I'm considering, I took a few hours to see if I could write a working garbage collector.

This is a very bare-bones copying GC, written without any reference to How To Do It Properly (just my knowledge of how a copying GC works, but I believe it is mostly cleanly written other than (a) the hardcoded pointer comparisons for object layouts, and (b) support for exactly one GC root, which happens to be the object at the lowest address. (It also calls a “heap” that which I believe is conventionally called a “space”. And I suppose someone could take issue with my placements of casts and void *s.)

The test program simply allocates a structure containing the strings “Hello” and “world”, allocates a bunch of junk, and then prints the strings to show that they are still intact.

gc.c )

A dreadful thing

Saturday, October 4th, 2008 10:32
some type *foo;
size_t count = ...;

...

foo = malloc(count * sizeof * foo);