</>
Skip to content
C lessons (9/28)

C — Constants

Two ways to define constants

C provides two primary mechanisms:

#include <stdio.h>

// Method 1: Preprocessor macro
#define PI 3.14159
#define MAX_SIZE 100

// Method 2: const keyword
const double E = 2.71828;
const int BUFFER_SIZE = 4096;

int main() {
    printf("PI: %f\n", PI);
    printf("E: %f\n", E);
    return 0;
}

#define macros

The preprocessor replaces every occurrence before compilation:

#include <stdio.h>

#define GREETING "Hello, world!"
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define SQUARE(x) ((x) * (x))

int main() {
    printf("%s\n", GREETING);

    int a = 5, b = 3;
    printf("Max: %d\n", MAX(a, b));     // 5
    printf("Square: %d\n", SQUARE(4));   // 16
    printf("Square: %d\n", SQUARE(a + 1)); // 36

    return 0;
}

Always wrap macro parameters in parentheses to avoid precedence bugs:

// BAD: without parentheses
#define SQUARE_BAD(x) x * x
// SQUARE_BAD(2 + 1) → 2 + 1 * 2 + 1 → 5 (wrong!)

// GOOD: with parentheses
#define SQUARE_GOOD(x) ((x) * (x))
// SQUARE_GOOD(2 + 1) → ((2 + 1) * (2 + 1)) → 9 (correct!)

const keyword

const creates a read-only variable with proper type checking:

#include <stdio.h>

int main() {
    const int MAX = 100;
    const float PI = 3.14159f;
    const char *name = "Alice";  // Pointer to constant string

    printf("Max: %d\n", MAX);
    printf("PI: %f\n", PI);
    printf("Name: %s\n", name);

    // MAX = 200;       // Compiler error: assignment of read-only variable
    // PI = 3.14;       // Compiler error

    return 0;
}

#define vs const

Feature#defineconst
Type safetyNo (text replacement)Yes (compiler checks)
ScopeFile-wide (until #undef)Block-scoped
DebuggableNo (invisible to debugger)Yes
MemoryNo memory allocatedAllocated in memory
Can be &-addressedNoYes
#include <stdio.h>

#define MAX_ITEMS 50   // No type, no memory, no scope
const int LIMIT = 50;  // Typed, uses memory, scoped

int main() {
    // int *p = &MAX_ITEMS;    // Error: macro has no address
    const int *p = &LIMIT;    // OK: const has an address
    printf("Address of LIMIT: %p\n", (void *)p);
    return 0;
}

Enums as constants

For groups of related integer constants:

#include <stdio.h>

enum { RED = 1, GREEN, BLUE };         // 1, 2, 3
enum { OK = 200, NOT_FOUND = 404, SERVER_ERROR = 500 };

int main() {
    printf("Red: %d\n", RED);         // 1
    printf("Green: %d\n", GREEN);      // 2
    printf("Not Found: %d\n", NOT_FOUND); // 404
    return 0;
}

String constants

#include <stdio.h>

#define APP_NAME "My Application"
const char *const APP_VERSION = "2.1.0";

int main() {
    printf("%s v%s\n", APP_NAME, APP_VERSION);

    // String literal arrays
    const char *days[] = {
        "Monday", "Tuesday", "Wednesday",
        "Thursday", "Friday", "Saturday", "Sunday"
    };

    for (int i = 0; i < 7; i++) {
        printf("%s\n", days[i]);
    }
    return 0;
}

Array constants

#include <stdio.h>

#define MAX_GRADES 5

int main() {
    const int grades[MAX_GRADES] = {95, 87, 92, 78, 88};

    int sum = 0;
    for (int i = 0; i < MAX_GRADES; i++) {
        sum += grades[i];
    }

    printf("Average: %.1f\n", (double)sum / MAX_GRADES);
    return 0;
}

Conditional compilation with constants

Use #define for compile-time configuration:

#include <stdio.h>

#define DEBUG 1
#define VERSION 3

int main() {
    #if DEBUG
        printf("Debug mode enabled\n");
        printf("Version: %d\n", VERSION);
    #else
        printf("Production mode\n");
    #endif

    #if VERSION >= 3
        printf("Using new features\n");
    #else
        printf("Using legacy features\n");
    #endif

    return 0;
}

Best practices

  • Use const for typed constants with scope
  • Use #define for compile-time configuration and macros
  • Always parenthesize macro parameters
  • Use enums for related sets of integer constants
  • Use UPPER_CASE naming for constants

Mini Practice

Write C code that:

  1. Defines PI using both #define and const
  2. Creates a macro MAX(a, b) that returns the larger value
  3. Uses an enum for days of the week
  4. Uses #define for a compile-time debug flag

Up Next

In the next lesson, you'll learn about Operators — arithmetic, bitwise, and logical operations.

Related Topics

Frequently Asked Questions about Constants

What is Constants in C?

Constants is a fundamental concept in C. This lesson explains it step by step with clear examples, making it easy for beginners to understand.

How do I learn Constants?

Start by reading the explanation above, then try the code examples. Practice by modifying the examples and experimenting with different values. Hands-on practice is the best way to learn Constants.

Why is Constants important in C?

Constants is essential for C development. Understanding this concept will help you write better code and solve real-world problems more effectively.