🔑 C Keywords

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.

AspectKeywordIdentifier
DefinitionReserved word with fixed meaning defined by the C standardName chosen by the programmer for a variable, function, etc.
Who defines itThe C language specification (ISO/IEC 9899)The programmer, following naming rules
Can it be reused?❌ Never — always reserved✅ Any name not already in use in that scope
Case sensitivityAlways lowercase in standard C (e.g. int, not Int)Case-sensitive; Total and total are different
Examplesint, if, return, struct, whiletotalMarks, calculateArea, studentCount
Total count32 in C89; more added by later standardsUnlimited — as many as your program needs

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.

🔢
Data Type Keywords (5)

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.

📏
Type Modifier Keywords (4)

short, long, signed, unsigned — adjust the size or sign behaviour of a base data type, letting you fine-tune memory usage and value range.

💾
Storage Class Keywords (4)

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).

🔀
Control Flow Keywords (5)

if, else, switch, case, default — direct which block of statements actually executes based on a condition, forming the backbone of decision-making logic.

🔁
Looping Keywords (3)

for, while, do — repeat a block of statements either a fixed number of times or until a condition becomes false, avoiding repetitive manual code.

↪️
Jump Keywords (4)

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.

🏗️
Derived Type Keywords (4)

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.

🛡️
Qualifier & Utility Keywords (3)

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.

KeywordCategoryPurpose in One Line
autoStorage ClassDefault storage class for local variables (rarely written explicitly)
breakJumpExits a loop or switch statement immediately
caseControl FlowDefines a branch inside a switch statement
charData TypeDeclares a single character (1 byte) variable
constQualifierMarks a variable's value as unmodifiable after initialisation
continueJumpSkips the rest of the current loop iteration
defaultControl FlowThe fallback branch in a switch statement when no case matches
doLoopBegins a do-while loop that runs at least once
doubleData TypeDeclares a double-precision floating-point variable
elseControl FlowDefines the alternative branch of an if statement
enumDerived TypeDefines a set of named integer constants
externStorage ClassDeclares a variable or function defined in another file
floatData TypeDeclares a single-precision floating-point variable
forLoopBegins a counter-controlled loop
gotoJumpJumps unconditionally to a labelled statement
ifControl FlowBegins a conditional branch
intData TypeDeclares an integer variable
longType ModifierExtends the size/range of int or double
registerStorage ClassSuggests storing a variable in a CPU register for speed
returnJumpExits a function, optionally sending back a value
shortType ModifierReduces the size/range of int
signedType ModifierExplicitly allows negative and positive values
sizeofUtilityReturns the size in bytes of a type or variable at compile time
staticStorage ClassPreserves a variable's value between function calls / limits linkage
structDerived TypeGroups different data types together under one name
switchControl FlowSelects one of many code blocks to execute
typedefDerived TypeCreates a new name (alias) for an existing type
unionDerived TypeGroups different data types sharing the same memory location
unsignedType ModifierRestricts a variable to zero and positive values only
voidData TypeRepresents 'no value' — used for functions that return nothing
volatileQualifierTells the compiler a variable may change unexpectedly (e.g. hardware)
whileLoopBegins a condition-controlled loop

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()).

🖥️ Cdata_type_keywords.c
#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.

TypeTypical SizeTypical Range
short int2 bytes-32,768 to 32,767
int4 bytes-2,147,483,648 to 2,147,483,647
long int4 or 8 bytesAt least -2,147,483,648 to 2,147,483,647
long long int8 bytesAbout -9.2 quintillion to 9.2 quintillion
unsigned int4 bytes0 to 4,294,967,295
unsigned char1 byte0 to 255

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.

🖥️ Cstatic_example.c
#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.

🖥️ Cswitch_example.c
#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.

🖥️ Cloop_keywords.c
#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.

🖥️ Cjump_keywords.c
#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.

🖥️ Cderived_types.c
#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.

🖥️ Cqualifiers.c
#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.

📝 Read Next WordLexical analyser scans source code
scans characters
🔍 Extract Character SequenceStops at whitespace / symbol
word extracted
📖 Check Reserved Word TableCompare against the 32+ C keywords
match found
🔑 Classify as KEYWORDe.g. int, if, return
tagged as keyword
🏷️ Classify as IDENTIFIERe.g. total, calculateArea
tagged as identifier
➡️ Pass Token to ParserBuilds the syntax tree
token stream continues
✅ Continue CompilationNext stage: syntax & semantic check

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.

StandardYearNew Keywords AddedPurpose
C89 / C901989(original 32)First ANSI/ISO standardisation of the language
C991999inline, restrict, _Bool, _Complex, _ImaginaryPerformance hints, boolean type, complex number support
C112011_Alignas, _Alignof, _Atomic, _Generic, _Noreturn, _Static_assert, _Thread_localMemory alignment, atomics for threading, generic macros, compile-time assertions
C17 / C182018(none)Bug fixes and clarifications only — no new keywords
C232023/2024nullptr, true, false, bool, typeof, typeof_unqual, constexpr, thread_local, static_assert, alignas, alignofModernised syntax; many _Xxx keywords gained cleaner lowercase aliases

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

✅ Advantages
Learning Keywords by CategoryGrouping keywords by purpose (data types, loops, jumps) instead of memorising an alphabetical list makes recall far faster and more intuitive during actual coding.
Reading Compiler Errors CarefullyErrors like 'expected identifier before int' are the compiler directly telling you a keyword was used where a name was expected — learning to read these messages precisely saves debugging time.
Using const DeliberatelyMarking values that should never change with const catches accidental modification bugs at compile time instead of during testing.
Avoiding Leading UnderscoresNever starting identifiers with an underscore sidesteps the entire reserved-identifier confusion described above.
❌ Disadvantages
Using a Keyword as a Variable NameAttempting int float = 10; fails because float is reserved — a surprisingly common mistake among absolute beginners still learning the list.
Forgetting break in a switch StatementOmitting break after a case causes execution to 'fall through' into the next case unintentionally — one of the most notorious C beginner bugs.
Overusing gotoNew programmers sometimes discover goto and overuse it for flow control that if/else or loops would express far more clearly and safely.
Confusing signed char and unsigned charAssuming char is always signed (or always unsigned) is implementation-defined behaviour — code that depends on this assumption can behave differently across compilers.
Treating register as GuaranteedBelieving register forces a variable into a CPU register — in reality it is only a hint the compiler is free to ignore entirely.

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.

Easy

2. Why does the statement int static = 10; fail to compile?

Easy

3. 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); }?

Medium

4. Explain why enum Color { RED, GREEN, BLUE }; makes BLUE equal to 2 without writing any numbers explicitly.

Medium

5. What is wrong with this declaration: const int total; total = 50;?

Medium

6. What is the difference between while (count < 10) and do { ... } while (count < 10); in terms of guaranteed execution?

Medium

7. Why might a professional C codebase almost never contain the goto keyword, even though it is perfectly legal?

Hard

8. A beginner writes unsigned int age = -5; and it compiles without error. What actually happens, and why is this dangerous?

Hard

Conclusion — 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.

CategoryKeyword CountMost Used In Practice
Data Types5Every single variable and function declaration
Type Modifiers4Fine-tuning memory usage and value ranges
Storage Classes4Controlling variable lifetime and visibility
Control Flow5Decision-making logic (if/switch)
Loops3Repetition (for/while/do)
Jumps4Early exits and function returns
Derived Types4Modelling real-world composite data
Qualifiers/Utility3Read-only values and compile-time size queries

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. 🔑

Frequently Asked Questions (FAQ)