C Tutorial — Learn C Programming
Key takeaway: This free C tutorial teaches you systems programming from scratch — variables, pointers, arrays, functions, structs, and memory management — with practical code examples you can compile and run.
C is a general-purpose, procedural programming language created in 1972. It is used for operating systems, embedded systems, game engines, and performance-critical applications. This tutorial is for beginners, CS students, and developers who want to understand how computers work at a low level.
Last updated: September 2026
Preprocessor Directives in C
The C preprocessor processes your source code before compilation. It handles directives that begin with # and performs text substitution, file inclusion, and conditional compilation.
#define - Macro Definition
#include <stdio.h>
// Object-like macros
#define PI 3.14159
#define MAX_SIZE 100
#define GREETING "Hello, World!"
// Function-like macros
#define SQUARE(x) ((x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define PRINT_VAR(var) printf(#var " = %d\n", var)
int main() {
int radius = 5;
float area = PI * SQUARE(radius);
printf("Area of circle: %.2f\n", area);
printf("Maximum of 10 and 20: %d\n", MAX(10, 20));
int number = 42;
PRINT_VAR(number); // Prints: number = 42
return 0;
}Conditional Compilation
#include <stdio.h>
#define DEBUG 1
#define VERSION 2
int main() {
printf("Program started\n");
#ifdef DEBUG
printf("Debug mode is ON\n");
#endif
#ifndef RELEASE
printf("This is not a release build\n");
#endif
#if VERSION == 1
printf("Version 1.0\n");
#elif VERSION == 2
printf("Version 2.0\n");
#else
printf("Unknown version\n");
#endif
#if defined(DEBUG) && DEBUG > 0
printf("Advanced debugging enabled\n");
#endif
return 0;
}Predefined Macros
#include <stdio.h>
int main() {
printf("File: %s\n", __FILE__);
printf("Line: %d\n", __LINE__);
printf("Date: %s\n", __DATE__);
printf("Time: %s\n", __TIME__);
printf("Function: %s\n", __func__);
#ifdef __STDC__
printf("Standard C compiler\n");
#endif
#ifdef __STDC_VERSION__
printf("C Standard version: %ld\n", __STDC_VERSION__);
#endif
return 0;
}Macro Operators
#include <stdio.h>
// Stringification operator (#)
#define STRINGIFY(x) #x
#define PRINT_EXPR(expr) printf(#expr " = %d\n", expr)
// Token pasting operator (##)
#define CONCAT(a, b) a##b
#define DECLARE_VAR(type, name) type var_##name
int main() {
// Stringification
printf("Stringified: %s\n", STRINGIFY(Hello World));
int x = 10, y = 20;
PRINT_EXPR(x + y); // Prints: x + y = 30
// Token pasting
int CONCAT(num, 1) = 100; // Creates variable num1
int CONCAT(num, 2) = 200; // Creates variable num2
printf("num1 = %d, num2 = %d\n", num1, num2);
// Declare variables using macro
DECLARE_VAR(int, count); // Creates int var_count
DECLARE_VAR(float, price); // Creates float var_price
var_count = 5;
var_price = 19.99;
printf("Count: %d, Price: %.2f\n", var_count, var_price);
return 0;
}Macro Best Practices:
- Use parentheses around macro parameters and entire expression
- Use ALL_CAPS for macro names
- Be careful with side effects in function-like macros
- Consider using const variables instead of #define for simple constants