C keywords are predefined by the C compiler and they are lowercase in C89. Since there are only 32, why can't one define them as case-insensitive?
-
2Because it makes the tokenizer simpler. This was a strong reason way back when memory and program size was measured in kbytes. – Jens Dec 18 '16 at 16:48
-
1Note that in C11, there are 44 keywords, and 10 of them are mixed case. In C99, two keywords (`inline` and `restrict`) were added that are lower-case, plus three mixed-case keywords (`_Bool`, `_Complex`, `_Imaginary`). – Jonathan Leffler Dec 18 '16 at 16:58
2 Answers
Because C is case-sensitive and those are the keywords. Making them case-insensitive would have made the compiler slower, but the real reason is that's how it was defined.
There was a lot of experimentation with letter case in the 60s. For a while, BCPL reserved lowercase words as system keywords to distinguish from user names, which had to be uppercase, or single-letter lowercase. But then they switched to uppercase (and later back to lowercase), and whether it was case sensitive depended on the compiler. Same was true for FORTRAN/Fortran, which generally isn't case sensitive at all, but sometimes is in wildly complicated ways.
So when I say "it would have made the compiler slower," I don't mean "because it's an older language and processor time was more precious." Most modern languages are case sensitive. Many older languages have varying amounts of case sensitivity over their history and implementations. But fundamentally case sensitivity is simpler for computers. It's how most of Unix is designed, and C (originally B) was built to be the system language for Unix. But again, this was just a particular design decision in Unix, not some "it must be this way" deep choice.
But all of this is just talking around and back-justifying the answer. The answer is: because that's how C is defined.

- 1
- 1

- 286,113
- 34
- 456
- 610
-
2And with C99 onwards, some keywords are mixed case — `_Bool`, `_Alignof`, `_Alignas`, `_Complex`, `_Imaginary`, `_Noreturn`, `_Thread_local`, `_Atomic`, `_Generic`, `_Static_assert`. – Jonathan Leffler Dec 18 '16 at 16:46
You can:
#include <ctype.h>
#include <string.h>
#include <stdio.h>
char const * const kw[]={
"_Alignas",
"_Alignof",
"_Atomic",
"auto",
"_Bool",
"break",
"case",
"char",
"_Complex",
"const",
"continue",
"default",
"do",
"double",
"else",
"enum",
"extern",
"float",
"for",
"_Generic",
"goto",
"if",
"_Imaginary",
"inline",
"int",
"long",
"_Noreturn",
"register",
"restrict",
"return",
"short",
"signed",
"sizeof",
"static",
"_Static_assert",
"struct",
"switch",
"_Thread_local",
"typedef",
"union",
"unsigned",
"void",
"volatile",
"while",
};
static int comb(char * s, int ix, char const * orig){
if(s[ix]==0){
if(0!=strcmp(s,orig))
return -(0>printf("#define %s %s\n", s, orig));
return 0;
}
s[ix]=tolower(s[ix]);
if(0>comb(s,ix+1,orig))
return -1;
s[ix]=toupper(s[ix]);
if(0>comb(s,ix+1,orig))
return -1;
return 0;
}
static int mk_defines(char const* s){
char b[20];
int len = strlen(s);
memcpy(b,s,len+1);
if(0>comb(b,0,s))
return -1;
return 0;
}
int main()
{
int n = sizeof(kw)/sizeof(kw[0]);
for(int i=0;i<n;i++){
if(0>mk_defines(kw[i]))
return -1;
}
return 0;
}
And it's only 29,694 defines (yea!).

- 58,047
- 6
- 95
- 142
-
1I kind of wonder how much this would pessimize preprocessing times. – Petr Skocik Dec 18 '16 at 16:58