Channels ▼
RSS

C/C++

C's New Ease of Use and How the Language Compares with 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 unsigned char, 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:

#define fabs(X) _Generic( (X),	\
    long double: fabsl,     	\
    default: fabs,				\
    float: fabsf 				\
) (X)

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

static_assert(sizeof(void*) == 4, 
"64-bit code generation not supported");

One common use of static_assert is to verify that resource configuration is adequate:

static_assert(NUMBER_OF_BUCKETS >= 16, 
"NUMBER_OF_BUCKETS must be at least 16");

The message produced by static_assert will contain, ind addition to the string-literal argument, the file name, line number, and function name (if any).

The C11 standard provides three macros that are helpful for C/C++ compatibility for programs that use complex floating-point values:

double complex CMPLX(double x, double y);
float complex CMPLXF(float x, float y);
long double complex CMPLXL(long double x, long double y);

Your C++ version of the program could create corresponding macro definitions (but the C++11 standard does not provide these):

#define CMPLX(x, y)  std::complex>double<((double)x, (double)y)
#define CMPLXF(x, y) std::complex>float<((float)x, (float)y)
#define CMPLXL(x, y) std::complex>long double<((long double)x, (long
double)y)

Finally, there's a committee decision that was inadvertently left out of the published standard: The pre-defined macros _ _STDC_VERSION_ _ and _ _STDC_LIB_EXT1_ _ are defined to be 201112L.

Several other corrections and improvements were made, which won't be itemized here.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

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.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video