Geoff Chappell - Software Analyst
A keyword is an identifier to which the compiler assigns a formal meaning during tokenisation, such that the identifier is in general reserved for the compiler’s interpretation of the language and is not usable for naming code or data.
Note however that this generality has two broad exceptions. One is provided by the preprocessor: a keyword can be redefined by a macro and thus hidden from the compiler. Another exception is provided by the compiler itself: a keyword can be referred to explicitly as an identifier by giving it as an argument to __identifier (though some need enclosure in double-quotes).
Some identifiers become keywords only in some conditions. Many depend on command-line options (most notably /clr, /noBool, /ZB, /Zc:wchar_t and /Ze). Some are keywords in C++ but not in C. Where the table below lists no condition, the identifier is recognised as a keyword by both the C and C++ compilers in all circumstances.
Of the command-line options that affect the list of keywords, -ZE and -Zf are not known to CL.EXE but can be passed to the front-end compiler modules indirectly, via the /d1 option. The term “managed build” is shorthand for any of the C1XX options -Gil, -Gmanaged or -Goptil, the first of which is an ordinary outcome of giving CL the /clr option.
Though keywords are C/C++ identifiers when examined as text, they do not tokenise as identifiers. See, for instance, that
#pragma message rubbish // C4083 #pragma message void // C4081
produces two different warnings, the first to complain about the identifier rubbish, the second just about (the token) void.
Among the several hundred types of token recognised by the compiler are many that are dedicated to keywords and operators. Tokenisation maps each keyword to one of these dedicated tokens. Multiple keywords can map to the same token.
The text of a keyword is for all practical purposes lost during tokenisation. Error and warning messages that cite the token show the standard text for that token, which may differ from the text that actually produced the token. For instance, the warning produced by
#pragma message __alignof // C4081
complains about finding something called __builtin_alignof. Similarly, where a keyword is given as input to __identifier for conversion back to an identifier, the text given for the keyword is long gone and the name produced for the identifier is the standard name of the keyword as a token. For instance, in the function declaration
int __identifier (__alignof) (void *); // C4932 if /Ze
the name given to the function is __builtin_alignof. Moreover, the warning, C4932, at level 4 and not raised at all if compiled with /Za, speaks only of confusion over whether __builtin_alignof has one or two leading underscores.
For each keyword, the table below shows the standard text of the corresponding token, if this differs from the text of the keyword.
Many identifiers that are defined as keywords are disabled, as a special case of keyword tokenisation. Every disabled keyword maps to the one token, just for disabled keywords, which gets discarded from the token stream after showing a warning (C4226, C4233, C4234, C4235 or C4236). For instance, in
#pragma message __huge rubbish // C4226 and C4083
retrieval of the disabled-keyword token that represents the text __huge produces warning C4226, after which __huge may as well have been white space.
With keywords acting essentially as reserved words in the language, a master list is surely helpful. In the table below of keywords recognised by Microsoft Visual C++ version 13.00.9466, those that are omitted from the product documentation’s list of C++ Keywords are highlighted yellow. They are not all undocumented: they are just not included in what the documentation seems to present as its master list. Some are mentioned elsewhere in the product documentation, even as keywords. Some are disabled, mostly as being obsolete or unsupported (in this product). All nonetheless are keywords and “cannot be used as identifiers in your program” any more than can the identifiers that Microsoft does happen to list as keywords.
The product documentation lists __m64, __m128, __m128d, __m128i and __noop as keywords. They may be significant to the compiler, and in interesting ways, but they are not actually implemented as keywords and they are therefore not listed as keywords in these notes.
Keyword | Conditions to be Keyword | Tokenisation |
---|---|---|
__abstract | C++ and managed build | |
__alignof | __builtin_alignof | |
_alignof | /Ze or -ZE | __builtin_alignof |
and | C++ and not /Ze | && |
and_eq | C++ and not /Ze | &= |
__asm | ||
_asm | /Ze or -ZE | __asm |
asm | C++ | |
__assume | ||
_assume | /Ze or -ZE | __assume |
auto | ||
__based | ||
_based | /Ze or -ZE | __based |
bitand | C++ and not /Ze | & |
bitor | C++ and not /Ze | | |
bool | C++ and neither /noBool nor /Ze | |
__box | C++ and managed build | |
break | ||
__builtin_alignof | ||
_builtin_alignof | /Ze or -ZE | __builtin_alignof |
__builtin_isfloat | disabled (warning C4235) | |
case | ||
catch | C++ | |
__cdecl | ||
_cdecl | /Ze or -ZE | __cdecl |
cdecl | /Ze | __cdecl |
char | ||
class | C++ | |
__compileBreak | ||
_compileBreak | /Ze or -ZE | __compileBreak |
compl | C++ and not /Ze | ~ |
const | ||
const_cast | C++ | |
continue | ||
__declspec | ||
_declspec | /Ze or -ZE | __declspec |
default | ||
__delegate | C++ and managed build | |
delete | C++ | |
do | ||
double | ||
dynamic_cast | C++ | |
else | ||
enum | ||
__event | C++ and /Ze | |
__except | ||
_except | /Ze or -ZE | __except |
explicit | C++ | |
__export | disabled (warning C4236) | |
_export | /Ze or -ZE | disabled (warning C4236) |
extern | ||
false | C++ and not /noBool | |
__far | disabled (warning C4226) | |
_far | /Ze or -ZE | disabled (warning C4226) |
far | /Ze or -Zf | disabled (warning C4226) |
__far16 | disabled (warning C4226) | |
_far16 | /Ze or -ZE | disabled (warning C4226) |
__fastcall | ||
_fastcall | /Ze or -ZE | __fastcall |
__feacpBreak | ||
_feacpBreak | /Ze or -ZE | __feacpBreak |
__finally | ||
_finally | /Ze or -ZE | __finally |
float | ||
for | ||
__forceinline | ||
_forceinline | /Ze or -ZE | __forceinline |
__fortran | disabled (warning C4226) | |
_fortran | /Ze or -ZE | disabled (warning C4226) |
fortran | /Ze or -Zf | disabled (warning C4226) |
friend | C++ | |
__gc | C++ and managed build | |
goto | ||
__hook | C++ and /Ze | |
__huge | disabled (warning C4226) | |
_huge | /Ze or -ZE | disabled (warning C4226) |
huge | /Ze or -Zf | disabled (warning C4226) |
__identifier | ||
if | ||
__if_exists | C++ and /Ze | |
__if_not_exists | C++ and /Ze | |
__inline | inline | |
_inline | /Ze or -ZE | inline |
inline | C++ | |
int | ||
__int128 | disabled (warning C4235) | |
__int16 | ||
_int16 | /Ze or -ZE | __int16 |
__int32 | ||
_int32 | /Ze or -ZE | __int32 |
__int64 | if /ZB < 64, disabled (warning C4235) | |
_int64 | /Ze or -ZE, and /ZB ≥ 64 | __int64 |
__int8 | ||
_int8 | /Ze or -ZE | __int8 |
__interface | C++ and /Ze | |
__leave | ||
_leave | /Ze or -ZE | __leave |
long | ||
__multiple_inheritance | if C, disabled (warning C4233) | |
_multiple_inheritance | C++ and either /Ze or -ZE | __multiple_inheritance |
mutable | C++ | |
namespace | C++ | |
__near | disabled (warning C4226) | |
_near | /Ze or -ZE | disabled (warning C4226) |
near | /Ze or -Zf | disabled (warning C4226) |
new | C++ | |
__nodefault | disabled (warning C4235) | |
__nogc | C++ and managed build | |
__nontemporal | disabled (warning C4235) | |
not | C++ and not /Ze | ! |
not_eq | and not /Ze | != |
__nounwind | disabled (warning C4234) | |
__novtordisp | if C, disabled (warning C4233) | |
_novtordisp | C++ and either /Ze or -ZE | __novtordisp |
operator | C++ | |
or | C++ and not /Ze | || |
or_eq | C++ and not /Ze | |= |
__pascal | disabled (warning C4226) | |
_pascal | /Ze or -ZE | disabled (warning C4226) |
pascal | /Ze or -Zf | disabled (warning C4226) |
__pin | C++ and managed build | |
__pragma | ||
_pragma | /Ze or -ZE | __pragma |
private | C++ | |
__probability | disabled (warning C4235) | |
__property | C++ and managed build | |
protected | C++ | |
__ptr32 | ||
_ptr32 | /Ze or -ZE | __ptr32 |
__ptr64 | ||
_ptr64 | /Ze or -ZE | __ptr64 |
public | C++ | |
__raise | C++ and /Ze | |
register | ||
reinterpret_cast | C++ | |
__restrict | disabled (warning C4235) | |
__resume | disabled (warning C4234) | |
return | ||
__sealed | C++ and managed build | |
__serializable | disabled (warning C4226) | |
_serializable | /Ze or -ZE | disabled (warning C4226) |
short | ||
signed | ||
__single_inheritance | if C, disabled (warning C4233) | |
_single_inheritance | C++ and either /Ze or -ZE | __single_inheritance |
sizeof | ||
static | ||
static_cast | C++ | |
__stdcall | ||
_stdcall | /Ze or -ZE | __stdcall |
struct | ||
__super | C++ and /Ze | |
switch | ||
__sysapi | disabled (warning C4235) | |
__syscall | disabled (warning C4226) | |
_syscall | /Ze or -ZE | disabled (warning C4226) |
template | C++ | |
this | C++ | |
__thiscall | if C, disabled (warning C4234); if C++ and not -Binl, disabled (warning C4234) |
|
_thiscall | C++ and -Binl and either /Ze or -ZE | __thiscall |
throw | C++ | |
__transient | disabled (warning C4226) | |
_transient | /Ze or -ZE | disabled (warning C4226) |
true | C++ and not /noBool | |
__try | ||
_try | /Ze or -ZE | __try |
try | C++ | |
__try_cast | C++ | |
typedef | ||
typeid | C++ | |
typename | C++ | |
__typeof | C++ and managed build | |
__unaligned | disabled (warning C4235) | |
__unhook | C++ and /Ze | |
union | ||
unsigned | ||
using | C++ | |
__uuidof | if C, disabled (warning C4233) | |
_uuidof | C++ and either /Ze or -ZE | __uuidof |
__value | C++ and managed build | |
virtual | C++ | |
__virtual_inheritance | if C, disabled (warning C4233) | |
_virtual_inheritance | C++ and either /Ze or -ZE | __virtual_inheritance |
void | ||
volatile | ||
__w64 | ||
_w64 | /Ze or -ZE | __w64 |
__wchar_t | ||
wchar_t | C++ and /Zc:wchar_t | __wchar_t |
while | ||
xor | C++ and not /Ze | ^ |
xor_eq | C++ and not /Ze | ^= |