What Is C For?

C is no longer used in as many places as it once was, but it still remains popular with people looking to get close to the hardware. David Chisnall looks at the limitations of the current C standard and produces a wish list for the next version.

From the author of

From the author of

Since C was originally standardized in 1989, two major versions of the
language specification have been released: C89 and C99. With a new version
coming out every 10 years, it’s about time for another one.

C has always been a slightly confused language. It was created as a simple
language from which it was easy to generate machine code for implementing UNIX
in a way that wasn’t tied to a specific architecture. Of course, this is
nonsense, because any language as low-level as C makes a lot of assumptions
about the underlying architecture. One obvious example in C is that of a flat
address space—C has no mechanism for controlling segmentation, because
this feature wasn’t available on the machines for which the language was
designed.

Vectors

One of the big changes in the last 10 years is that pretty much every CPU now has some form of vector processor. Unfortunately, it’s impossible to write code in C for that vector processor. Currently, programmers handle the problem in the following ways:

Use inline assembly.

Use intrinsic functions (very thin wrappers around CPU instructions).

Use compiler extensions.

The first two alternatives make the code non-portable across architectures; the last makes it non-portable across compilers.

The way GCC handles the last approach is quite nice. Vector types can be declared with a specified size and then can be used in the same way as scalar quantities. But I’d like to see a vector keyword added to the C standard so this can be done without relying on hacks like GCC’s __attribute__ extension. Vectors should be defined in a way similar to arrays, or via a typedef, so that the following would be valid:

typedef vector int[4] int4;

When you created an int4, you would get a vector of four integers. Any operation performed on it would then be performed on all of the elements. All of the basic operations on scalars, including those defined in math.h, should be extended to work on vector types.

A compiler targeting a chip that doesn’t support the operations would reduce them to sequences of scalar operations, exactly as GCC does now. For chips that have vector units, having the semantics of the operations specified in the code makes generating the correct instructions a lot easier than having to infer them from loops.