Keywords in C Programming Language
Every reserved word in C explained — grouped by category, with meaning, syntax, and working examples — plus the newer keywords added by C99, C11, and C23.
Last Updated
March 2026
Read Time
23 min
Level
Beginner
What are Keywords in C?
A keyword is a word that has been permanently reserved by the C language itself, carrying a fixed, non-negotiable meaning that the compiler recognises the instant it sees it. Words like int, if, while, and return are not suggestions or conventions — they are part of C's grammar, defined by the ISO C standard, and every conforming compiler must treat them identically.
Because keywords already carry meaning to the compiler, they can never be used as identifiers — you cannot name a variable int, a function return, or a struct for. Attempting to do so produces an immediate syntax error, because the compiler has no way to tell whether you mean the reserved word or a name you invented.
The original ANSI C standard (C89/C90) defined exactly 32 keywords — a remarkably small vocabulary compared to most modern languages. This minimalism is intentional: C's designers believed a small, orthogonal set of reserved words, combined with a rich standard library of ordinary functions, was more powerful and more predictable than baking dozens of special-purpose words into the language itself. Later standards — C99, C11, C17, and C23 — have added a handful of new keywords, but the philosophy of a small core vocabulary has remained largely intact for over 50 years.
This chapter walks through every keyword C offers, grouped by what it actually does, so that instead of memorising an unordered list of 32+ words, you build a mental map: 'these five words describe data types, these four control storage, these six manage control flow' — and so on. That map is what turns a list of reserved words into genuine understanding.
Keywords vs. Identifiers — The Core Distinction
Beginners often blur the line between keywords and identifiers because both are simply 'words' that appear in source code. The distinction, however, is absolute from the compiler's point of view.
A useful mental test: if you removed every keyword from the C language, you would have no grammar left — no way to declare a type, branch a condition, or loop. If you removed every identifier, you would still have a valid (if useless) grammar. Keywords are the skeleton of the language; identifiers are the flesh you add to describe your own program's data and logic.
The 32 Standard C Keywords — Grouped by Purpose
Rather than memorising an alphabetical list, it is far more useful to understand C's keywords in eight functional groups. Each group answers a different question about your program.
int, char, float, double, void — declare what kind of value a variable, function return, or parameter represents. These are the most frequently used keywords in any C program.
short, long, signed, unsigned — adjust the size or sign behaviour of a base data type, letting you fine-tune memory usage and value range.
auto, register, static, extern — control a variable's lifetime (how long it exists), scope (where it is visible), and storage location (stack, register, or static memory).
if, else, switch, case, default — direct which block of statements actually executes based on a condition, forming the backbone of decision-making logic.
for, while, do — repeat a block of statements either a fixed number of times or until a condition becomes false, avoiding repetitive manual code.
break, continue, goto, return — alter the normal top-to-bottom, sequential flow of a program, jumping out of loops, skipping iterations, or exiting functions early.
struct, union, enum, typedef — let you build your own composite or aliased data types out of C's built-in ones, essential for modelling real-world data.
const, volatile, sizeof — const and volatile qualify how a variable can be accessed or changed; sizeof is a compile-time operator that reports the size, in bytes, of a type or variable.
5 + 4 + 4 + 5 + 3 + 4 + 4 + 3 = 32 keywords — exactly matching the ANSI C89 standard. Every one of these words will appear repeatedly across your entire C learning journey, so the goal is not to memorise the count, but to recognise instantly which category any keyword belongs to when you see it in real code.
Complete List of C Keywords — Reference Table
Use this table as a quick reference while reading real C programs. Every keyword from the original ANSI C standard is listed with its category and a one-line description of its purpose.
Data Type Keywords in Detail
Data type keywords are the most frequently typed words in any C program, since every single variable, function parameter, and return value needs one. C provides five basic type keywords, each representing a fundamentally different kind of data at the hardware level.
int — Whole Numbers
int declares a variable that holds a whole number, positive or negative, with no decimal component. On most modern systems it occupies 4 bytes, giving a range of roughly -2.1 billion to +2.1 billion. It is by far the most commonly used data type keyword in C — counters, indexes, and general-purpose whole numbers almost always use int.
char — Single Characters
char declares a variable holding a single character, stored internally as a small integer (1 byte) representing that character's position in the ASCII table. char grade = 'A'; actually stores the number 65 in memory — C treats characters and small integers almost interchangeably, a detail that surprises many beginners the first time they see it.
float and double — Decimal Numbers
float (4 bytes, roughly 6-7 significant digits of precision) and double (8 bytes, roughly 15-16 significant digits) both store numbers with a decimal point, using the IEEE-754 floating-point standard. double is the default choice for most calculations requiring accuracy — scientific, financial, or engineering code almost always prefers it over float unless memory is extremely constrained, as on small embedded devices.
void — The Absence of a Type
void is unusual among data type keywords because it represents the deliberate absence of a value. It appears in three distinct contexts: as a function's return type (void printMessage(void) — returns nothing), as a function's parameter list (meaning it accepts no arguments), and as a generic pointer type (void *ptr — a pointer that can point to any data type, commonly returned by malloc()).
#include <stdio.h>
void printBanner(void) { // void: no return value, no parameters
printf("=== Report ===\n");
}
int main() {
int totalStudents = 42; // int: whole number
char grade = 'A'; // char: single character
float averageMarks = 78.5f; // float: single-precision decimal
double preciseGPA = 3.8724561; // double: high-precision decimal
printBanner();
printf("Students: %d | Grade: %c | Avg: %.1f | GPA: %lf\n",
totalStudents, grade, averageMarks, preciseGPA);
return 0;
}Type Modifier Keywords in Detail
Type modifiers attach to a base data type keyword to fine-tune its size or the range of values it can represent. They never appear alone — long by itself is meaningless without an implied or explicit int.
- ▶
short — Reduces the storage size of int, typically to 2 bytes, giving a smaller range (-32,768 to 32,767) but saving memory. Written as short int or simply short.
- ▶
long — Increases the storage size, typically to 8 bytes for long int on 64-bit systems, allowing much larger whole numbers. long long int (C99+) guarantees at least 8 bytes on every platform.
- ▶
signed — Explicitly allows both negative and positive values. This is actually the default behaviour for int, so signed int and int are usually identical — the keyword exists mainly for clarity or for use with char, whose default signedness is implementation-defined.
- ▶
unsigned — Restricts a variable to zero and positive values only, effectively doubling the maximum positive value it can hold by not reserving a bit for the sign. Commonly used for sizes, counts, and array indices that can never legitimately be negative.
Storage Class Keywords in Detail
Storage class keywords answer three questions about a variable that have nothing to do with its data type: how long does it live (lifetime), where can it be seen from (scope), and where is it physically stored (memory location).
auto — The Invisible Default
Every local variable you declare inside a function is auto by default, whether or not you write the keyword. int x = 5; inside a function is identical to auto int x = 5;. Because it is the automatic default, this keyword is almost never written explicitly in modern C code — most programmers go years without typing it even once.
register — A Hint for Speed
register suggests to the compiler that a variable will be accessed very frequently and should, if possible, be kept in a fast CPU register rather than regular memory. Modern optimising compilers are far better at making this decision than programmers are, so register is now largely a historical curiosity — most style guides discourage using it in new code, though it remains legal syntax.
static — Persistence and Privacy
static has two distinct effects depending on where it is used. Inside a function, a static local variable retains its value between successive calls to that function, instead of being reset each time. At file scope (outside any function), static restricts a global variable or function's visibility to only that source file, preventing other files in a multi-file project from accessing it — a simple but powerful form of encapsulation in C.
extern — Sharing Across Files
extern declares that a variable or function is defined in a different source file, letting multiple .c files in the same project share a single global variable without each file re-creating its own copy. It is a declaration, not a definition — the actual storage is allocated exactly once, in whichever file omits the extern keyword.
#include <stdio.h>
void countCalls(void) {
static int calls = 0; // initialised only ONCE, ever
calls++;
printf("This function has been called %d time(s)\n", calls);
}
int main() {
countCalls(); // Output: called 1 time(s)
countCalls(); // Output: called 2 time(s)
countCalls(); // Output: called 3 time(s)
return 0;
}Control Flow Keywords in Detail
Control flow keywords let a program make decisions — executing one block of code instead of another, based on whether a condition is true or false at run time.
- ▶
if — Executes a block of statements only when its condition (in parentheses) evaluates to a non-zero (true) value.
- ▶
else — Provides an alternative block that runs only when the preceding if's condition was false. Can be chained as else if for multiple conditions.
- ▶
switch — Evaluates a single expression once and compares it against several possible constant values, jumping directly to the matching branch — often more readable than a long chain of else if statements.
- ▶
case — Defines one specific value to compare against inside a switch block. Each case is typically followed by a break to prevent execution from 'falling through' into the next case.
- ▶
default — The fallback branch inside a switch that runs when none of the case values match the switch expression — functionally similar to a final else.
#include <stdio.h>
int main() {
int day = 3;
switch (day) {
case 1:
printf("Monday\n");
break;
case 2:
printf("Tuesday\n");
break;
case 3:
printf("Wednesday\n");
break;
default:
printf("Another day\n");
}
return 0;
}Looping Keywords in Detail
Looping keywords let a block of code repeat automatically instead of being written out manually many times. C offers exactly three, each suited to a slightly different situation.
- ▶
for — Best when you know (or can calculate) how many times to repeat in advance. Combines initialisation, condition, and update into one compact line: for (int i = 0; i < 10; i++).
- ▶
while — Best when repetition depends purely on a condition, and the number of iterations is not known ahead of time. The condition is checked before each iteration, so the loop body may run zero times.
- ▶
do — Paired with while to form a do-while loop, where the condition is checked after each iteration. This guarantees the loop body runs at least once, regardless of the condition's initial value — useful for menu systems and input validation.
#include <stdio.h>
int main() {
// for: fixed number of repetitions
for (int i = 1; i <= 3; i++) {
printf("for loop: %d\n", i);
}
// while: condition-controlled, may run zero times
int count = 0;
while (count < 3) {
printf("while loop: %d\n", count);
count++;
}
// do-while: guaranteed to run at least once
int input;
do {
input = 5; // simulate a value received
printf("do-while loop ran with input %d\n", input);
} while (input != 5);
return 0;
}Jump Keywords in Detail
Jump keywords deliberately break the normal top-to-bottom, sequential flow of a program, transferring control somewhere else entirely.
- ▶
break — Immediately exits the nearest enclosing loop or switch statement, skipping any remaining iterations or cases entirely.
- ▶
continue — Skips the rest of the current loop iteration and jumps straight to the next one, without exiting the loop entirely.
- ▶
return — Exits the current function immediately, optionally sending a value back to whatever called it. Every function with a non-void return type must use return to send back its result.
- ▶
goto — Jumps unconditionally to a labelled statement anywhere else in the same function. Almost universally discouraged in modern C style, since overuse produces famously hard-to-follow 'spaghetti code' — its main legitimate remaining use is breaking out of deeply nested loops in a single step.
#include <stdio.h>
int main() {
for (int i = 1; i <= 5; i++) {
if (i == 4) break; // stop the loop entirely at 4
if (i == 2) continue; // skip printing 2, keep looping
printf("i = %d\n", i);
}
return 0; // exits main(), sends 0 back to the OS
}Derived Type Keywords in Detail
Derived type keywords let you build entirely new data types out of C's built-in ones — essential once your programs need to model real-world entities that a single int or float cannot represent alone.
- ▶
struct — Groups several different (or same) data types together under a single name, with each member occupying its own separate memory. Used to model composite records like a Student with a name, age, and GPA.
- ▶
union — Similar syntax to struct, but every member shares the exact same memory location, so only one member holds a valid value at any given moment. Used to save memory when a variable might hold one of several possible types.
- ▶
enum — Defines a set of named integer constants, making code far more readable than 'magic numbers'. enum Day { MON, TUE, WED } assigns MON=0, TUE=1, WED=2 automatically.
- ▶
typedef — Creates an alternate, often shorter or clearer, name for an existing type. typedef unsigned long ulong; lets you write ulong instead of unsigned long everywhere afterward.
#include <stdio.h>
struct Student { // struct: grouped, separate memory
char name[30];
int age;
float gpa;
};
enum Day { MON, TUE, WED, THU, FRI }; // enum: named constants
typedef struct Student StudentRecord; // typedef: shorter alias
int main() {
StudentRecord s1 = {"Aarav", 20, 8.7};
enum Day today = WED;
printf("%s is %d years old, GPA %.1f\n", s1.name, s1.age, s1.gpa);
printf("Day number: %d\n", today); // prints 2 (WED)
return 0;
}Qualifier & Utility Keywords in Detail
- ▶
const — Marks a variable as read-only after initialisation. const float PI = 3.14159; will cause a compile-time error if any later code attempts to modify PI. Widely used for values that must never change and for function parameters that should not be accidentally altered.
- ▶
volatile — Tells the compiler that a variable's value may change unexpectedly, outside the normal flow of the program — for example, a hardware register updated by an interrupt, or a variable shared with another thread. This prevents the compiler from applying aggressive optimisations that assume the value cannot change on its own.
- ▶
sizeof — A compile-time operator (not a function, despite the parentheses in typical usage) that returns the size, in bytes, of a type or variable. sizeof(int) commonly returns 4; sizeof(myArray) returns the total bytes an entire array occupies, useful for calculating element counts.
#include <stdio.h>
int main() {
const float PI = 3.14159; // cannot be reassigned later
int numbers[5] = {10, 20, 30, 40, 50};
printf("Size of int: %zu bytes\n", sizeof(int));
printf("Size of array: %zu bytes\n", sizeof(numbers));
printf("Element count: %zu\n", sizeof(numbers) / sizeof(numbers[0]));
// PI = 3.14; // Would cause a compile-time error
printf("PI = %.5f\n", PI);
return 0;
}How the Compiler Recognises a Keyword — Flowchart
It helps to see exactly what happens inside the compiler the moment it encounters a word like int or total in your source code. The flowchart below traces the decision process the lexical analyser (tokeniser) follows for every single word it reads.
Code Execution Flow — from source to output
This lookup happens for every single word in your program, thousands of times even in a modest-sized file, and it happens in roughly constant time thanks to how compilers implement their reserved-word table (commonly a hash table or perfect hash function). This is also exactly why you get an immediate, unambiguous error the moment you try to use a keyword as a variable name — the lexical analyser tags it as a keyword before the parser ever gets a chance to treat it as anything else.
Keywords Added by Later C Standards
The original 32 keywords have not stayed frozen forever. As C evolved through ISO standards, new keywords were carefully added — always as new reserved words that did not previously exist, so that old, valid C89 programs would continue to compile without modification.
Notice the pattern in C11: new keywords started with an underscore and capital letter (_Bool, _Atomic) specifically to avoid breaking any older program that might have already used a plain word like bool as a variable name. C23 then cleaned this up by introducing proper lowercase versions (bool, true, false) as genuine keywords, now that enough time had passed for the underscore versions to become the safe, established convention first.
Keywords vs. Reserved Identifiers — A Common Confusion
Beyond the formal keyword list, C also reserves certain patterns of identifiers for the compiler and standard library's own internal use — even though these are not, strictly speaking, keywords. Understanding this distinction prevents a category of subtle bugs that a beginner's compiler may not even warn about.
- ▶
Names starting with two underscores (__temp) — Reserved everywhere for the compiler and standard library. Never define your own identifiers this way.
- ▶
Names starting with underscore + capital letter (_Temp) — Also reserved everywhere, following the same pattern C11 used for its new keywords.
- ▶
Names starting with a single underscore at file scope (_temp) — Reserved for the implementation (compiler/library) when declared outside any function.
- ▶
Standard library function names (printf, malloc, strlen) — Not keywords (you technically can redeclare them, though compilers will warn heavily), but redefining them is almost always a serious mistake that breaks your program in confusing ways.
The safe, professional rule of thumb: never start your own identifiers with an underscore. This single habit avoids every one of these reserved-pattern collisions without needing to memorise the exact rules.
Common Mistakes Beginners Make With Keywords
C Keywords — Interview Questions
Interviewers frequently use keyword-based questions to quickly separate candidates who have written real C programs from those who have only skimmed the syntax.
Practice Questions — Test Your Understanding
1. Classify each of the following as a keyword or an identifier: return, myReturn, unsigned, unsignedValue, break.
Easy2. Why does the statement int static = 10; fail to compile?
Easy3. What is the output of a for loop with an empty condition, such as for (int i = 0; ; i++) { if (i == 3) break; printf("%d\n", i); }?
Medium4. Explain why enum Color { RED, GREEN, BLUE }; makes BLUE equal to 2 without writing any numbers explicitly.
Medium5. What is wrong with this declaration: const int total; total = 50;?
Medium6. What is the difference between while (count < 10) and do { ... } while (count < 10); in terms of guaranteed execution?
Medium7. Why might a professional C codebase almost never contain the goto keyword, even though it is perfectly legal?
Hard8. A beginner writes unsigned int age = -5; and it compiles without error. What actually happens, and why is this dangerous?
HardConclusion — Mastering C's Reserved Vocabulary
Keywords are the smallest possible unit of meaning C's designers considered important enough to bake directly into the language, rather than leaving to ordinary library functions. That restraint — only 32 words in the original standard, growing modestly over five decades — is precisely why C has remained learnable, stable, and portable across generations of hardware and compilers.
You now know every standard C keyword, organised into eight functional groups: data types, type modifiers, storage classes, control flow, loops, jumps, derived types, and qualifiers. You have also seen how the compiler itself distinguishes a keyword from an identifier during tokenisation, and how later standards — C99, C11, and C23 — carefully extended this vocabulary without breaking decades of existing code.
The natural next step is C Identifiers and Variables, where the naming rules briefly introduced here get their full, dedicated treatment, followed by C Data Types, which expands deeply on the five data type keywords covered in this chapter. Keep this keyword reference close — you will return to it constantly as you read and write real C code.
32 words. That's all it takes to describe C's entire grammar. Everything else you will ever write in C — however large or complex — is built from combinations of these reserved words and your own identifiers. 🔑