Constants

Some values should never change: the number of days in a week, a tax rate, the size of a buffer. C gives you three ways to name them — const variables, #define macros and enum constants — and each has its place.

const variables

const makes a variable read-only. The compiler rejects any attempt to change it:

C
#include <stdio.h>

int main(void) {
    const double VAT_RATE = 0.20;
    VAT_RATE = 0.25;
    printf("%.2f\n", VAT_RATE);
    return 0;
}
Compiler error
main.c:5:14: error: cannot assign to variable 'VAT_RATE' with const-qualified type 'const double'

A const variable has a type, follows normal scope rules and shows up in the debugger — the safest choice for most constants.

C
#include <stdio.h>

int main(void) {
    const double VAT_RATE = 0.20;
    const int DAYS_PER_WEEK = 7;
    double net = 50.0;
    printf("Gross: %.2f\n", net * (1 + VAT_RATE));
    printf("Weeks in 365 days: %d\n", 365 / DAYS_PER_WEEK);
    return 0;
}
Output
Gross: 60.00
Weeks in 365 days: 52

#define macros

The preprocessor replaces a macro name with its text before compiling (lesson 4). Macros have no type and no scope, but they work anywhere a literal value is needed, such as array sizes in older C:

C
#include <stdio.h>

#define MAX_NAME 32
#define PI 3.14159265358979

int main(void) {
    char name[MAX_NAME] = "Ada";
    double r = 2.0;
    printf("%s: room for %d characters\n", name, MAX_NAME);
    printf("Circle area: %.3f\n", PI * r * r);
    return 0;
}
Output
Ada: room for 32 characters
Circle area: 12.566

No = and no semicolon in a #define: #define MAX_NAME = 32; would paste = 32; everywhere. By convention macro names are all capitals.

enum constants

An enum defines a set of named integer constants. They're ideal for related values and are real constant expressions:

C
#include <stdio.h>

enum { BOARD_SIZE = 8, MAX_PLAYERS = 4 };
enum weekday { MONDAY = 1, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY };

int main(void) {
    int board[BOARD_SIZE];
    printf("%zu squares in a row\n", sizeof board / sizeof board[0]);
    printf("Wednesday is day %d\n", WEDNESDAY);
    printf("Up to %d players\n", MAX_PLAYERS);
    return 0;
}
Output
8 squares in a row
Wednesday is day 3
Up to 4 players

Values count up from the previous one, so TUESDAY is 2. Lesson 43 covers enums fully.

Which to use

const#defineenum
Has a typeYesNoint
Respects scopeYesNo — applies to the rest of the fileYes
Usable as an array size at file scope / in case labelsNo (before C23's constexpr)YesYes
Non-integer valuesYesYesNo
Best forTyped values, especially double and stringsConditional compilation, values shared through headersInteger constants and sets of choices

C23 adds constexpr, which combines the advantages of const and true constant expressions (lesson 55).

Literals

A value written directly in code is a literal: 42, 3.5, 'x', "hello". Numbers with no explanation are called magic numbers — if (temp > 37.5) is clearer as if (temp > FEVER_THRESHOLD). Name the constant once, and changing it later means editing one line.

Try it yourself

Replace the magic numbers with named constants.

Try it yourself · main.c
Edit the code, copy it into main.c, then compile and run it with cc -std=c17 -Wall main.c -o main && ./main. How to set up a C compiler
Output
2 days, 7 hours, 33 minutes, 20 seconds