What are the most useful new features in C99?

CC99

C Problem Overview


C99 has been around for over 10 years, but support for it has been slow coming, so most developers have stuck with C89. Even today, I'm sometimes mildly surprised when I come across C99 features in C code.

Now that most major compilers support C99 (MSVC being a notable exception, and some embedded compilers also lagging behind), I feel that developers who work with C probably ought to know about what C99 features are available to them. Some of the features are just common features that were never standardized before (snprintf, for instance), or are familiar from C++ (flexible variable declaration placement, or single-line // comments), but some of the new features were first introduced in C99 and are unfamiliar to many programmers.

What do you find the most useful new features in C99?

For reference, the C99 standard (labelled as a draft, but identical to the updated standard, as far as I know), the list of new features, and the GCC C99 implementation status.

One feature per answer, please; feel free to leave multiple answers. Short code examples demonstrating new features are encouraged.

C Solutions


Solution 1 - C

I'm so used to typing

for (int i = 0; i < n; ++i) { ... }

in C++ that it's a pain to use a non-C99 compiler where I am forced to say

int i;
for (i = 0; i < n; ++i ) { ... }

Solution 2 - C

stdint.h, which defines int8_t, uint8_t, etc. No more having to make non-portable assumptions about how wide your integers are.

uint32_t truth = 0xDECAFBAD;

Solution 3 - C

I think that the new initializer mechanisms are extremely important.

struct { int x, y; } a[10] = { [3] = { .y = 12, .x = 1 } };

OK - not a compelling example, but the notation is accurate. You can initialize specific elements of an array, and specific members of a structure.

Maybe a better example would be this - though I'd admit it isn't hugely compelling:

enum { Iron = 26, Aluminium = 13, Beryllium = 4, ... };

const char *element_names[] =
{
    [Iron]      = "Iron",
    [Aluminium] = "Aluminium",
    [Beryllium] = "Beryllium",
    ...
};

Solution 4 - C

Support for one-line comments beginning with //.

Solution 5 - C

Variable length arrays:

int x;
scanf("%d", &x);
int a[x];
for (int i = 0; i < x; ++i)
	a[i] = i * i;
for (int i = 0; i < x; ++i)
	printf("%d\n", a[i]);

Solution 6 - C

Being able to declare variables at locations other than the start of a block.

Solution 7 - C

Variadic macros. Makes it easier to generate boilerplate code with unlimited number of arguments.

Solution 8 - C

snprintf() - seriously, it's worth a lot to be able to do safe formatted strings.

Solution 9 - C

Compound literals. Setting structures member-by-member is so '89 ;)

You can also use them to get pointers to objects with automatic storage duration without declaring unnecessary variables, eg

foo(&(int){ 4 });

insteand of

int tmp = 4;
foo(&tmp);

Solution 10 - C

Flexible array members.

>6.7.2.1 Structure and union specifiers

>As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member. With two exceptions, the flexible array member is ignored. First, the size of the structure shall be equal to the offset of the last element of an otherwise identical structure that replaces the flexible array member with an array of unspecified length) Second, when a . (or ->) operator has a left operand that is (a pointer to) a structure with a flexible array member and the right operand names that member, it behaves as if that member were replaced with the longest array (with the same element type) that would not make the structure larger than the object being accessed; the offset of the array shall remain that of the flexible array member, even if this would differ from that of the replacement array. If this array would have no elements, it behaves as if it had one element but the behavior is undefined if any attempt is made to access that element or to generate a pointer one past it.

Example:

typedef struct {
  int len;
  char buf[];
} buffer;

int bufsize = 100;
buffer *b = malloc(sizeof(buffer) + sizeof(int[bufsize]));

Solution 11 - C

The bool type.

You can now do something like that:

bool v = 5;

printf("v=%u\n", v);

will print

1

Solution 12 - C

Support for inline functions.

Solution 13 - C

Compound literals, already mentioned but here's my compelling example:

struct A *a = malloc(sizeof(*a));
*a = (struct A){0};  /* full zero-initialization   */
/* or */
*a = (struct A){.bufsiz=1024, .fd=2};   /* rest are zero-initialized.  */

It's a clear way to initialize data even if it's on the heap. There is no way to forget to zero-initialize something.

Solution 14 - C

The restrict keyword. Especially when you crunch numbers...

Solution 15 - C

Unicode escape sequence support:

printf("It's all \u03B5\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC to me.\n");

Or even, literal Unicode characters:

printf("日本語\n");

(note: may not work depending on your locale; portable support for different encodings will take more work than this)

Solution 16 - C

Hexadecimal floating point constants (0x1.8p0f) and conversion specifiers (%a, %A). If you deal with low-level numerical details frequently, these are an enormous improvement over decimal literals and conversions.

They save you from worries about rounding when specifying constants for an algorithm, and are immensely useful for debugging low-level floating-point code.

Solution 17 - C

Personally, I like the acknowledgment of IEC 60559:1989 (Binary floating-point arithmetic for microprocessor systems) and much better floating-point support.

In a similar vein, setting and querying the floating-point rounding mode, checking for Nan/Infinity/subnormal numbers, etc., is great to have.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBrian CampbellView Question on Stackoverflow
Solution 1 - CJon ReidView Answer on Stackoverflow
Solution 2 - CBrian CampbellView Answer on Stackoverflow
Solution 3 - CJonathan LefflerView Answer on Stackoverflow
Solution 4 - CgameoverView Answer on Stackoverflow
Solution 5 - CmmxView Answer on Stackoverflow
Solution 6 - CmikecshView Answer on Stackoverflow
Solution 7 - CkennytmView Answer on Stackoverflow
Solution 8 - CDavid ThornleyView Answer on Stackoverflow
Solution 9 - CChristophView Answer on Stackoverflow
Solution 10 - CGregory PakoszView Answer on Stackoverflow
Solution 11 - CPatrick SchlüterView Answer on Stackoverflow
Solution 12 - CCodeRainView Answer on Stackoverflow
Solution 13 - Cu0b34a0f6aeView Answer on Stackoverflow
Solution 14 - CAlexandre C.View Answer on Stackoverflow
Solution 15 - CBrian CampbellView Answer on Stackoverflow
Solution 16 - CStephen CanonView Answer on Stackoverflow
Solution 17 - CAlok SinghalView Answer on Stackoverflow