17
$\begingroup$

C99 introduced the following keywords: _Bool _Complex _Imaginary inline restrict

Why _Bool _Complex and _Imaginary instead of just bool complex and imaginary? To preserve backwards compatibility for existing codebases that might use bool complex or imaginary.

However, if that was a problem, why would that not have been a problem with inline and restrict too? How was C99 able to get away with adding those keywords directly rather than as _Underscored keywords?

$\endgroup$
1

4 Answers 4

21
$\begingroup$

Problems caused by reserving restrict and inline are pretty easy to fix (since the program will no longer compile), problems caused by reserving typenames are not.

This is supported by the official C99 rationale (emphasis mine):

It is recognized that each added keyword will require some existing code that used it as an identifier to be rewritten. No meaningful programs are known to be quietly changed by adding the new keywords.

restrict and inline can never appear in a place where we could have a user-defined typename in C99:

In the case of restrict: T *restrict name; The only things that can appear here are qualifiers, such as const or volatile, so no existing programs in C would have been using restrict here.

In the case of inline: inline T name(params...); Once again, a typename cannot appear here.

The only programs that could be broken by reserving these can cause are things that use restrict or inline as an identifier or typename, which are both easy to fix, since the program will not compile at all:

e.g. int restrict = 10;. (just rename it)

With types (bool, complex, etc) however, you can get much bigger problems:

Say you have a bit of code that was built with C89, and used complex as an (incomplete) typename:

void f(complex* a, complex* b, complex* out);

Now, if we change the meaning of complex in C99, we can silently break this program in a way that's harder to fix: The code including the header thinks complex refers to our shiny new C99 type, whereas the version of f in our TU that we compiled with our C89 compiler thinks that complex refers to some user-defined type. This can then break at runtime, possibly much later, and be much more painful to track down and fix.

The C rationale also provides an additional justification for complex and imaginary specifically:

_Complex and _Imaginary, not complex and imaginary, are keywords in order that freestanding implementations are not required to support complex. Old code using the names complex or imaginary will still work (assuming <complex.h> is not included), and combined C/C++ implementations will not have to finesse C-only public keywords.

Regarding why the C11 keywords all use underscores, my guess would be the committee has gotten stricter about backwards compatibility since C99 (since technically restrict and inline are breaking changes).

$\endgroup$
6
  • 1
    $\begingroup$ Also, between 1999 and 2011, a lot more code got published online, so it was possible for the C standards committee to see what identifier names were being used in practice. $\endgroup$ Commented Feb 6 at 16:54
  • 3
    $\begingroup$ The official C99 rationale supports the general idea of this answer: "It is recognized that each added keyword will require some existing code that used it as an identifier to be rewritten" but "No meaningful programs are known to be quietly changed by adding the new keywords." (emphasis added). The rationale does not go into further detail. $\endgroup$ Commented Feb 7 at 12:41
  • $\begingroup$ @JohnBollinger thanks for tracking this down, I'll make an edit later $\endgroup$ Commented Feb 7 at 14:25
  • $\begingroup$ I wonder what downsides there would have been, if any, to having a syntax allowing the specification of exported symbols, so that a program which needed to link to an external library file named restrict could declare something like` int __name("restrict") qrestrict(void);, after which any references to restrict` would use linker symbol qrestrict? This could also improve interop with linker-generated names including characters like dollar signs, which some implementations allow in identifiers but others don't, since a C compiler could pass anything in the string to the linker. $\endgroup$ Commented Feb 10 at 18:39
  • $\begingroup$ @supercat I don't think it's particularly helpful to support that, since most linkers have options that allow you to rename symbols pretty easily. $\endgroup$ Commented Feb 11 at 20:52
6
$\begingroup$

According to the C99 Rationale document (section 6.4.1):

Several keywords were added in C89: const, enum, signed, void and volatile. New in C99 are the keywords inline, restrict, _Bool, _Complex and _Imaginary.

Where possible, however, new features have been added by overloading existing keywords, as, for example, long double instead of extended. It is recognized that each added keyword will require some existing code that used it as an identifier to be rewritten. No meaningful programs are known to be quietly changed by adding the new keywords.

The keywords entry, fortran, and asm have not been included since they were either never used, or are not portable. Uses of fortran and asm as keywords are noted as common extensions.

_Complex and _Imaginary, not complex and imaginary, are keywords in order that freestanding implementations are not required to support complex. Old code using the names complex or imaginary will still work (assuming <complex.h> is not included), and combined C/C++ implementations will not have to finesse C-only public keywords.

Reference

  1. https://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf
$\endgroup$
4
$\begingroup$

This is also “just an educated guess”, but I suspect that bool, complex, and imaginary had much more existing use than inline or restrict did.

Before bool became an official part of the C language, it was pretty common for programmers to define their own Boolean type in order to help document the fact that a variable represented a 0/1 truth value. For example, the Microsoft Windows headers include typedef int BOOL;, and it's not too far-fetched to think that others were using lowercase bool to make their fake Boolean type look more like a keyword.

Similarly, complex numbers are popular with mathematicians and electrical engineers, and it's likely that existing programs had code like typedef struct {double real; double imaginary;} complex; which would break if imaginary and complex were reserved words.

In contrast, inline had little reason to have been used as an identifier (unless maybe your program dealt with the arrangement of cylinders in a car engine?), and had pre-1999 use as a compiler extension (e.g., in GCC) for inline functions, the way it's now officially used in C. Making inline a keyword was just standardizing what programmers were already doing with non-standard compiler extensions.

And while restrict could have been used as a function or variable name, it's not very self-documenting unless you add another word or two to specify what is being restricted. So likely rarely used by itself.

$\endgroup$
1
  • 3
    $\begingroup$ "unless maybe your program dealt with the arrangement of cylinders in a car engine?" Or, more plausibly, if your program is a compiler. $\endgroup$ Commented Feb 6 at 20:09
4
$\begingroup$

Bjarne Stroustrup discusses the introduction of bool in C and C++ in Sibling Rivalry: C and C++. The C approach was to require a new header stdbool.h to use bool. But as Stroustrup points out, this doesn't help backwards compatibility as much as you'd think. As soon as a header file has #include <stdbool.h>, anything including that header (transitively) must be compatible with the new name, and can no longer use bool as an identifier. You get increasingly tangled up with preprocessor magic trying to protect existing code from the new definition. In the end, it's probably easier to avoid the header and use the _Bool keyword directly if you are programming in C99.

The proposed C23 standard does add bool as a first class keyword.

$\endgroup$
1
  • $\begingroup$ "The proposed C23 standard does add bool as a first class keyword." - and why should they be able to get away with it this time, if they couldn't before? $\endgroup$ Commented May 21 at 20:18

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.