Best c99 questions in May 2012

What are the incompatible differences betweeen C(99) and C++(11)?

36 votes

This question was triggered by replie(s) to a post by Herb Sutter where he explained MS's decision to not support/make a C99 compiler but just go with the C(99) features that are in the C++(11) standard anyway.

One commenter replied:

(...) C is important and deserves at least a little bit of attention.

There is a LOT of existing code out there that is valid C but is not valid C++. That code is not likely to be rewritten (...)

Since I only program in MS C++, I really don't know "pure" C that well, i.e. I have no ready picture of what details of the C++-language I'm using are not in C(99) and I have little clues where some C99 code would not work as-is in a C++ compiler.

Note that I know about the C99 only restrict keyword which to me seems to have very narrow application and about variable-length-arrays (of which I'm not sure how widespread or important they are).

Also, I'm very interested whether there are any important semantic differences or gotchas, that is, C(99) code that will compiler under C++(11) but do something differently with the C++ compiler than with the C compiler.


Quick links: External resources from the answers:

If you start from the common subset of C and C++, sometimes called clean C (which is not quite C90), you have to consider 3 types of incompatibilities:

  1. Additional C++ featues which make legal C illegal C++

    Examples for this are C++ keywords which can be used as identifiers in C or conversions which are implicit in C but require an explicit cast in C++.

    This is probably the main reason why Microsoft still ships a C frontend at all: otherwise, legacy code that doesn't compile as C++ would have to be rewritten.

  2. Additional C features which aren't part of C++

    The C language did not stop evolving after C++ was forked. Some examples are variable-length arrays, designated initializers and restrict. These features can be quite handy, but aren't part of any C++ standard, and some of them will probably never make it in.

  3. Features which are available in both C and C++, but have different semantics

    An example for this would be the linkage of const objects or inline functions.

A list of incompatibilities between C99 and C++98 can be found here (which has already been mentioned by Mat).

While C++11 and C11 got closer on some fronts (variadic macros are now available in C++, variable-length arrays are now an optional C language feature), the list of incompatibilities has grown as well (eg generic selections in C and the auto type-specifier in C++).

As an aside, while Microsoft has taken some heat for the decision to abandon C (which is not a recent one), as far as I know no one in the open source community has actually taken steps to do something about it: It would be quite possible to provide many features of modern C via a C-to-C++ compiler, especially if you consider that some of them are trivial to implement. This is actually possible right now using Comeau C/C++, which does support C99.

However, it's not really a pressing issue: Personally, I'm quite comfortable with using GCC and Clang on Windows, and there are proprietary alternatives to MSVC as well, eg Pelles C or Intel's compiler.

"int" really required to be at least as large as "short" in C?

14 votes

I've read a couple of times in different sources (e.g. Wikipedia: http://en.wikipedia.org/wiki/C_variable_types_and_declarations#Size), that in C, a long long is not smaller than a long, which is not smaller than an int, which is not smaller than a short.

However, I've looked this up in the C90 and C99 standards, and haven't found a corresponding clause. I've found only that C90 and C99 specifiy the minimum type sizes (Section 5.2.4.2.1 in C90 and C99 standards), but not their sizes in relation to each other. Have I missed something in the standards?

6.3.1.1 defines the relative integer conversion ranks of any two integer types. This is an abstract concept that's meant only to define the relationship between two types; there is no value defined as the rank of any type.

6.2.5p8 says:

For any two integer types with the same signedness and different integer conversion rank (see 6.3.1.1), the range of values of the type with smaller integer conversion rank is a subrange of the values of the other type.

It doesn't say anything about their relative sizes, and in fact it's theoretically possible for a conforming (but deliberately perverse) implementation to have sizeof (short) > sizeof (int). This is possible only if short has more padding bits (bits that don't contribute to the value) than int. This is very unlikely; most implementations don't have padding bits at all, and I know of no implementations where the relationships of the ranges of integer types differ from the relationships of their sizes.

Reference: either N1256, the latest C99 draft, or N1570, the latest C2011 draft.