C Notes
Learn about constants in C programming — const keyword, #define macro, enum constants, and literal constants with practical examples and best practices.
In everyday life, some values never change — the speed of light, the number of days in a week, or the value of pi. In C programming, we often work with values that should remain fixed throughout the program's execution. That's exactly what constants are for.
A constant is a value that, once defined, cannot be altered by the program during execution. Using constants makes your code safer, more readable, and easier to maintain.
Ways to Define Constants in C
C provides several ways to create constants:
| Method | Syntax | Scope | Type-checked |
|---|---|---|---|
const keyword | const int MAX = 100; | Block/file | Yes |
#define macro | #define MAX 100 | File (from point of definition) | No |
enum | enum { MAX = 100 }; | Block/file | Yes |
| Literal constants | 42, 'A', 3.14 | N/A (inline) | Yes |
1. The const Keyword
The const qualifier tells the compiler that a variable's value must not change after initialization. It's the most modern and type-safe way to define constants.
#include <stdio.h>
int main() {
const int MAX_SCORE = 100;
const float PI = 3.14159;
const char NEWLINE = '\n';
printf("Maximum score: %d\n", MAX_SCORE);
printf("Value of PI: %.5f\n", PI);
printf("Newline character: %c", NEWLINE);
// MAX_SCORE = 200; // ERROR: assignment to read-only variable
return 0;
}Maximum score: 100 Value of PI: 3.14159 Newline character:
Key Points About const
- Must be initialized at the time of declaration
- The compiler enforces immutability — any modification attempt causes a compile error
- Has proper scope (local or global depending on where declared)
- Occupies memory like a normal variable
- Type-checked by the compiler (catches type mismatch errors)
const with Pointers
Using const with pointers can be tricky. There are three variations:
#include <stdio.h>
int main() {
int x = 10, y = 20;
// Pointer to constant data — can't modify *p1
const int *p1 = &x;
// *p1 = 30; // ERROR
p1 = &y; // OK — pointer itself can change
// Constant pointer — can't modify p2 itself
int *const p2 = &x;
*p2 = 30; // OK — data can be modified
// p2 = &y; // ERROR
// Constant pointer to constant data — nothing can change
const int *const p3 = &x;
// *p3 = 40; // ERROR
// p3 = &y; // ERROR
printf("x = %d\n", x);
return 0;
}x = 30
| Declaration | Modify data (*p) | Modify pointer |
|---|---|---|
| const int *p | No | Yes |
| int *const p | Yes | No |
| const int *const p | No | No |
Summary of const with pointers
2. The #define Preprocessor Macro
The #define directive creates a symbolic constant that gets replaced by the preprocessor before compilation. It's essentially a text substitution mechanism.
#include <stdio.h>
#define PI 3.14159
#define MAX_SIZE 100
#define GREETING "Hello, World!"
int main() {
float radius = 5.0;
float area = PI * radius * radius;
printf("Area of circle: %.2f\n", area);
printf("Max array size: %d\n", MAX_SIZE);
printf("%s\n", GREETING);
return 0;
}Area of circle: 78.54 Max array size: 100 Hello, World!
How #define Works
When the preprocessor encounters #define PI 3.14159, it replaces every occurrence of PI in the code with 3.14159 before the compiler even sees it. It's pure text replacement.
#define vs const — Which to Use?
| Feature | #define | const |
|---|---|---|
| Type checking | No | Yes |
| Memory allocation | No (text replacement) | Yes |
| Debugging | Harder (name not in symbol table) | Easier |
| Scope | From definition to end of file (or #undef) | Block or file scope |
Can be used in switch cases | Yes | No (in C89) |
| Can define expressions | Yes | No |
| Visible in debugger | No | Yes |
Macro with Expressions
#define SQUARE(x) ((x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))Warning: Always wrap macro parameters in parentheses to avoid unexpected operator precedence issues.
3. Enum Constants
Enumerations (enum) create a set of named integer constants. They're especially useful when you have a group of related constants.
#include <stdio.h>
enum Days {
SUNDAY = 0,
MONDAY, // 1
TUESDAY, // 2
WEDNESDAY, // 3
THURSDAY, // 4
FRIDAY, // 5
SATURDAY // 6
};
enum Colors {
RED = 1,
GREEN = 2,
BLUE = 4
};
int main() {
enum Days today = WEDNESDAY;
enum Colors favorite = BLUE;
printf("Wednesday is day number: %d\n", today);
printf("Blue color code: %d\n", favorite);
if (today == WEDNESDAY) {
printf("It's midweek!\n");
}
return 0;
}Wednesday is day number: 3 Blue color code: 4 It's midweek!
Properties of Enum Constants
- By default, the first value is 0 and each subsequent value increments by 1
- You can assign specific values to any enumerator
- Enum constants are of type
int - Great for readability —
MONDAYis clearer than1 - Type-checked by the compiler
Practical Use of Enums
System is ready Moving left
4. Literal Constants
Literal constants are fixed values written directly in the code. They don't have names — they're the raw values themselves.
Integer Literals
int decimal = 42; // decimal (base 10)
int octal = 052; // octal (base 8) — prefix 0
int hex = 0x2A; // hexadecimal (base 16) — prefix 0x
long big = 100000L; // long integer — suffix L
unsigned int positive = 42U; // unsigned — suffix UFloating-Point Literals
float f1 = 3.14f; // float — suffix f
double d1 = 3.14; // double (default)
double d2 = 2.5e3; // scientific notation: 2500.0
long double ld = 3.14L; // long double — suffix LCharacter Literals
char ch = 'A'; // single character
char newline = '\n'; // escape sequence
char tab = '\t'; // tab character
char null_char = '\0'; // null characterString Literals
char *msg = "Hello, C!"; // string literal
char *path = "C:\\Users\\file"; // escaped backslash
char *multiline = "Line one "
"Line two"; // concatenated stringsCommon Escape Sequences
| Escape Sequence | Meaning |
|---|---|
\n | Newline |
\t | Tab |
\\ | Backslash |
\' | Single quote |
\" | Double quote |
\0 | Null character |
\a | Alert (beep) |
\r | Carriage return |
Complete Example: Using All Types of Constants
#include <stdio.h>
#define COMPANY "TechCorp"
#define TAX_RATE 0.18
enum Department { HR, ENGINEERING, MARKETING, FINANCE };
int main() {
const int BASE_SALARY = 50000;
const int BONUS = 5000;
enum Department dept = ENGINEERING;
int total = BASE_SALARY + BONUS;
float tax = total * TAX_RATE;
float net = total - tax;
printf("Company: %s\n", COMPANY);
printf("Department: %d\n", dept);
printf("Base Salary: %d\n", BASE_SALARY);
printf("Bonus: %d\n", BONUS);
printf("Tax (%.0f%%): %.2f\n", TAX_RATE * 100, tax);
printf("Net Salary: %.2f\n", net);
return 0;
}Company: TechCorp Department: 1 Base Salary: 50000 Bonus: 5000 Tax (18%): 9900.00 Net Salary: 45100.00
Best Practices for Using Constants
- Use UPPERCASE names for constants (
MAX_SIZE,PI,BUFFER_LENGTH) - Prefer
constover#definefor type safety and debuggability - Use enums for related groups of integer constants
- Never use magic numbers — define named constants for all literal values
- Document the purpose of constants with comments when the name isn't self-explanatory
Interview Questions on Constants in C
Q1: What is the difference between const and #define in C?
const creates a typed, scoped variable that the compiler can type-check and that appears in the debugger. #define is a preprocessor text substitution — it has no type, no scope, and doesn't allocate memory. Modern C prefers const for most use cases.
Q2: Can you modify a const variable using a pointer?
Technically, you can bypass const using pointer casting (*(int*)&constVar = newValue;), but this leads to undefined behavior. The compiler may have optimized code assuming the value never changes.
Q3: Where are constants stored in memory?
const global variables are typically stored in the read-only data segment (.rodata). #define constants don't occupy separate memory — they're substituted inline. Enum constants are compile-time values.
Q4: Can #define have a semicolon at the end?
No, you should not put a semicolon after #define values. Since it's text substitution, the semicolon would be pasted everywhere the macro is used, potentially causing errors.
Q5: What are the advantages of using enum over #define for related constants?
Enums provide: (1) automatic sequential numbering, (2) type checking, (3) better debugging (values appear by name), (4) logical grouping of related values, and (5) scope management.
Summary
- Constants are values that cannot be changed during program execution.
- C provides four ways to define constants:
const,#define,enum, and literal constants. constis type-safe and scoped — preferred in modern C code.#defineperforms text substitution before compilation — no type checking.enumis ideal for groups of related integer constants.- Literal constants are unnamed fixed values used directly in code.
- Following naming conventions (UPPERCASE) makes constants easily identifiable.
- Using constants improves code readability, maintainability, and prevents accidental modifications.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Constants in C Programming.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this C Programming topic.
Search Terms
c-programming, c programming, programming, basics, constants, constants in c programming
Related C Programming Topics