C/C++

C's New Ease of Use and How the Language Compares with C++

By Tom Plum, June 03, 2012

C11 adds useful, handy features that match some of the additions to C++. However, key divergences mean that a few C11 features have no counterparts in C++.

The 2011 revision of the ISO standard for C (dubbed "C11") provides several ease-of-use features, most of which are compatible with C++11. In order to use the normal-looking names I'll show here, you need to include these headers: <stddef.h>, <stdlib.h>, <assert.h>, <complex.h>, <stdnoreturn.h>, <uchar.h>, <stdatomic.h>, and <stdalign.h>.

Alignment

C11 and C++11 both provide new syntax for specifying alignment. The expression alignof(type-name) designates the alignment of type-name; it is a constant expression, as is the familiar sizeof(type-name). (There's one exception in C: Applying sizeof to a variable length array, or VLA, produces a non-constant expression.) The expression alignof(char) is, of course, always 1.

There is a similar syntax for declarations:

int alignas(double) b;

specifies that b is an int, but is aligned suitably for a double. Or for a more realistic example,

alignas(double) unsigned char buf[sizeof(double)];

specifies that buf is an array of unsignedchar, whose size and alignment would be suitable to hold a double.

Alignment can be specified as an integer: alignas(constant-expression) specifies the constant-expression as an alignment. Thus, alignas(type-name) means the same thing as alignas(alignof(type-name)).

For each target platform, there is some type that has the largest alignment requirement; that type can be named by the typedef max_align_t, so a declaration that specifies alignas(max_align_t) requests an alignment that will be suitable for any type on that platform. If a program requests an alignment that is greater than alignof(max_align_t), the program is not portable because support for an over-aligned type is optional.

The C11 library provides aligned_alloc(size_t bound, size_t nbytes), which allocates nbytes of storage aligned on a bound boundary. The most common use case heard by the committee was to request a buffer aligned on a cache boundary (typically 32k or 64k); however, you have to check your own compiler's manual because the implementation gets to determine the valid alignments.

Unicode Strings and Constants

The new u8 prefix for strings creates a string (an array of char) that is encoded using the UTF-8 encoding. If your text editor and your compiler are using the ASCII representation (most are), then the string u8"John Doe" will contain the same characters as the ordinary string "John Doe". The crucial difference comes when your program needs to represent international characters beyond the basic 7-bit ASCII (English) characters. If your text editor and compiler can handle the characters, then your program could contain a string like u8"α Ä Ǽ Ω" and pass that string to the various C library functions that handle ordinary strings (arrays of char).

The UTF-8 encoding is increasingly popular; for example, it is the default encoding for XML. To the extent that you have a choice about character representations, it appears to me with the benefit of decades of hindsight, that UTF-8, using the u8 strings, is the simplest and best choice.

However, you may not have this simple choice, so C11 (and C++11) also provide several other Unicode representations. A string like u"αΩ"creates an array of char16_t values (encoded in UTF-16); similarly, a string like U"αΩ" creates an array of char32_t values (encoded in UTF-32). Also, there are character constants for char16_t and char32_t values, written as u'α' and U'α'. Unfortunately, if you need to use these more complex features, you may need to know about endian-ness, surrogate characters, differences between Windows and UNIX/Linux representations, and this overview article cannot provide enough details to address all those issues.

Type-Generic Macros

The C99 standard introduced type-generic macros into the standardized library. For example, you could invoke fabs(x), where x is either float, double, or long double. What happened auto-magically was that invocation of the type-generic macro abs would cause invocation of one of three separate library functions fabsf(float), fabs(double), or fabsl(long double). However, in C99, you had no opportunity to use the same magic for your own purposes. Now, in C11, you can create a fabs(x) that will be portable to any other C11 compiler:

This method defines a macro named fabs, which will cause the invocation of several different library functions, using the new C11 syntax for the _Generic keyword. That fabs macro is an ordinary macro defined in the preprocessor. For example, fabs could be undefined (using #undef). As you see, type-generic macros provide only a tiny portion of the full-blown overloading that is available in C++, but it's enough for purposes such as the type-generic math library.

Miscellaneous Ease-of-Use Features

It is now possible, in C11 and C++11, to inform the compiler that a function will not return. For example, exit is a function that does not return, so it can be declared like this:

noreturn void exit(int status);

Using noreturn in this way can assist the compiler's optimizer, possibly eliminating unnecessary warnings.

C11 and C++11also provide static_assert(constant-expr, string-literal); if the constant-expr is zero, then a diagnostic message containing the text of the string-literal will be printed. As the name implies, the static_assert is evaluated at compile time, so it can prevent compilation with incompatible options; for example

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task.
However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

Video

This month's Dr. Dobb's Journal

This month,
Dr. Dobb's Journal is devoted to mobile programming. We introduce you to Apple's new Swift programming language, discuss the perils of being the third-most-popular mobile platform, revisit SQLite on Android
, and much more!