Comprehensive C programming cheatsheet covering all fundamentals from basic syntax to advanced concepts. Includes data types, operators, control flow, arrays, strings, functions, pointers, memory management, structures, unions, file I/O, preprocessor directives, and standard libraries with practical code examples and best practices.
- Basic Structure & Hello World
- Data Types
- Variables & Constants
- Operators
- Input/Output
- Control Flow
- Arrays
- Strings
- Functions
- Pointers
- Dynamic Memory Allocation
- Structures
- Unions
- Enumerations
- Typedef
- File Handling
- Preprocessor Directives
- Common Libraries
#include <stdio.h> // Preprocessor directive
int main() { // Main function - entry point
printf("Hello, World!\n"); // Output to console
return 0; // Exit status (0 = success)
}Compilation:
gcc program.c -o program # Compile
./program # Run (Linux/Mac)
program.exe # Run (Windows)Multi-file compilation:
gcc file1.c file2.c -o program| Type | Size (bytes) | Format Specifier | Range |
|---|---|---|---|
char |
1 | %c |
-128 to 127 |
unsigned char |
1 | %c |
0 to 255 |
short |
2 | %hd |
-32,768 to 32,767 |
unsigned short |
2 | %hu |
0 to 65,535 |
int |
4 | %d / %i |
-2,147,483,648 to 2,147,483,647 |
unsigned int |
4 | %u |
0 to 4,294,967,295 |
long |
4 or 8 | %ld |
Platform dependent |
long long |
8 | %lld |
±9.22×10^18 |
float |
4 | %f |
±3.4×10^±38 (6-7 digits) |
double |
8 | %lf |
±1.7×10^±308 (15-16 digits) |
long double |
10-16 | %Lf |
Extended precision |
#include <stdio.h>
#include <stdbool.h> // For bool type (C99)
int main() {
int age = 25;
float price = 99.99;
double pi = 3.14159265359;
char grade = 'A';
bool is_valid = true; // C99 boolean
printf("Age: %d\n", age);
printf("Price: %.2f\n", price);
printf("Pi: %.10lf\n", pi);
printf("Grade: %c\n", grade);
printf("Valid: %d\n", is_valid); // Prints 1 for true
printf("Size of int: %zu bytes\n", sizeof(int));
return 0;
}int x; // Declaration
int y = 10; // Declaration + Initialization
int a = 5, b = 10, c = 15; // Multiple declaration
short int si;
long int li;
unsigned int ui;const int MAX_VALUE = 100; // Constant variable
#define PI 3.14159 // Preprocessor constant
#define MIN(x, y) ((x) < (y) ? (x) : (y)) // Macro
// Using enum for constants
enum {SUCCESS = 0, FAILURE = -1};int global_var; // Global - static duration
static int file_var; // File scope only
extern int ext_var; // Defined in another file
void func() {
auto int local = 10; // Local (default)
static int count; // Preserves value between calls
register int fast; // Suggests register storage
}float f = 3.14;
int i = (int)f; // Explicit casting
int j = f; // Implicit casting
double d = 5.67;
int result = (int)d + 10;+ // Addition
- // Subtraction
* // Multiplication
/ // Division (integer division truncates)
% // Modulus (remainder)
++ // Increment (pre: ++x, post: x++)
-- // Decrement (pre: --x, post: x--)== // Equal to
!= // Not equal to
> // Greater than
< // Less than
>= // Greater than or equal to
<= // Less than or equal to&& // Logical AND
|| // Logical OR
! // Logical NOT& // Bitwise AND
| // Bitwise OR
^ // Bitwise XOR
~ // Bitwise NOT (one's complement)
<< // Left shift
>> // Right shift= // Simple assignment
+= // Add and assign: x += 5 → x = x + 5
-= // Subtract and assign
*= // Multiply and assign
/= // Divide and assign
%= // Modulus and assign
&= // Bitwise AND and assign
|= // Bitwise OR and assign
^= // Bitwise XOR and assign
<<= // Left shift and assign
>>= // Right shift and assignsizeof() // Size of operator
& // Address of
* // Dereference pointer
? : // Ternary operator: condition ? true_val : false_val
, // Comma operator
. // Structure member access
-> // Structure pointer member accessExample:
int x = 10, y = 20;
int max = (x > y) ? x : y; // Ternary operator
int *ptr = &x; // Address of
int value = *ptr; // Dereference
int z = (x += 5, y -= 5); // Comma operator (z = 15)#include <stdio.h>
int main() {
// Output
printf("Formatted output\n");
putchar('A'); // Output single character
puts("String output"); // Output string with newline
// Input
int num;
char ch;
char str[50];
scanf("%d", &num); // Formatted input
ch = getchar(); // Get single character
gets(str); // Get string (unsafe! - deprecated)
fgets(str, 50, stdin); // Safe string input
return 0;
}%d, %i // Signed integer
%u // Unsigned integer
%f // Float
%lf // Double
%c // Character
%s // String
%p // Pointer address
%x, %X // Hexadecimal
%o // Octal
%e, %E // Scientific notation
%% // Percent sign
%zu // size_t (sizeof result)printf("%5d", 42); // Width: " 42" (right-aligned)
printf("%-5d", 42); // Width: "42 " (left-aligned)
printf("%05d", 42); // Zero-padded: "00042"
printf("%.2f", 3.14159); // Precision: "3.14"
printf("%10.2f", 3.14); // Width + precision: " 3.14"if (condition) {
// code
} else if (condition2) {
// code
} else {
// code
}
// Single line (no braces needed for single statement)
if (x > 0) printf("Positive\n");switch(expression) {
case value1:
// code
break; // Don't forget break!
case value2:
// code
break;
default:
// code
break;
}// For loop
for (int i = 0; i < 10; i++) {
printf("%d ", i);
}
// While loop
while (condition) {
// code
}
// Do-while loop (executes at least once)
do {
// code
} while (condition);
// Infinite loops
while(1) { /* code */ }
for(;;) { /* code */ }break; // Exit loop/switch immediately
continue; // Skip to next iteration
goto label; // Jump to label (use sparingly)
return; // Exit functionfor (int i = 0; i < 10; i++) {
if (i == 5) break; // Exit loop when i = 5
if (i % 2 == 0) continue; // Skip even numbers
printf("%d ", i); // Prints: 1 3
}// Declaration
int arr[5]; // Uninitialized
int arr2[5] = {1, 2, 3, 4, 5}; // Fully initialized
int arr3[5] = {1, 2}; // Partially initialized: {1,2,0,0,0}
int arr4[] = {1, 2, 3}; // Size determined automatically (3)
// Access
arr[0] = 10; // Index starts at 0
int x = arr[2]; // Read element
// Iteration
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]);
}
// Memory: contiguous allocation
int size = sizeof(arr) / sizeof(arr[0]); // Get array length// 2D Array
int matrix[3][3] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// 3D Array
int cube[2][3][4];
// Access
matrix[0][1] = 10; // Row 0, Column 1
// Iterate 2D array
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
printf("%d ", matrix[i][j]);
}
printf("\n");
}int arr[5] = {10, 20, 30, 40, 50};
int *ptr = arr; // Points to first element
// Equivalent expressions:
*(arr + 2) == arr[2] // Both access third element
ptr[3] == *(ptr + 3) // Both access fourth element// String as character array
char str1[20] = "Hello"; // Mutable
char str2[] = "World"; // Size determined automatically
char str3[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; // Explicit null terminator
// String as pointer (read-only typically)
char *str4 = "Hello"; // String literal - shouldn't modify#include <string.h>
char str1[20] = "Hello";
char str2[20] = "World";
char dest[50];
// Length
size_t len = strlen(str1); // Returns 5 (excludes '\0')
// Copy
strcpy(dest, str1); // dest = "Hello"
strncpy(dest, str2, 3); // Copy at most 3 chars
// Concatenation
strcat(str1, str2); // str1 = "HelloWorld" (ensure space!)
strncat(dest, str2, 3); // Append at most 3 chars
// Comparison
int cmp = strcmp(str1, str2); // 0 if equal, <0 if str1<str2
int cmp2 = strncmp(str1, str2, 3); // Compare first 3 chars
// Search
char *pos = strchr(str1, 'l'); // First occurrence of 'l'
char *pos2 = strstr(str1, "ell"); // First occurrence of substring
// Other useful functions:
strrev(dest); // Reverse string (not standard, common)
strupr(dest); // To uppercase (not standard)
strlwr(dest); // To lowercase (not standard)char name[50];
// Safe input
fgets(name, 50, stdin); // Includes newline if space permits
// Remove trailing newline from fgets
name[strcspn(name, "\n")] = '\0';
// Unsafe input (avoid!)
gets(name); // Buffer overflow risk!
scanf("%s", name); // Stops at whitespace
scanf("%[^\n]s", name); // Read until newline#include <stdlib.h>
int num = atoi("123"); // String to int
float f = atof("3.14"); // String to float
long l = atol("123456"); // String to long
// Better alternatives with error checking
char *endptr;
long num2 = strtol("123abc", &endptr, 10); // Base 10
double d = strtod("3.14", NULL);// Function prototype (declaration)
return_type function_name(parameter_type1, parameter_type2, ...);
// Function definition
return_type function_name(parameter_type1 param1, parameter_type2 param2) {
// body
return value; // if return_type is not void
}
// Examples
int add(int a, int b); // Prototype
int add(int a, int b) { // Definition
return a + b;
}
void greet(void) { // No parameters, no return
printf("Hello!\n");
}
int main() {
int sum = add(5, 3); // Function call
greet();
return 0;
}// Pass by value (copy)
void modify(int x) {
x = 100; // Doesn't affect original
}
// Pass by reference (using pointers)
void modify_ptr(int *x) {
*x = 100; // Modifies original
}
// Pass array (decays to pointer)
void print_array(int arr[], int size) {
// arr[0] changes affect original array
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
}
// Const parameter (prevents modification)
void print_const(const int *arr, int size) {
// arr[0] = 10; // Error - const prevents modification
}int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int main() {
int (*operation)(int, int); // Function pointer declaration
operation = add; // Assign function
int result = operation(5, 3); // Call through pointer (result = 8)
operation = &subtract; // & is optional
result = operation(5, 3); // result = 2
// Array of function pointers
int (*ops[2])(int, int) = {add, subtract};
result = ops[0](10, 5); // Calls add: result = 15
return 0;
}int factorial(int n) {
if (n <= 1) return 1; // Base case
return n * factorial(n - 1); // Recursive case
}
int fibonacci(int n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}int x = 10;
int *ptr; // Pointer declaration
ptr = &x; // Assign address of x
int y = *ptr; // Dereference: y = 10
*ptr = 20; // Modify through pointer: x now = 20
printf("Value: %d\n", x); // 20
printf("Address: %p\n", &x); // Memory address
printf("Pointer: %p\n", ptr); // Same address
printf("Pointed value: %d\n", *ptr); // 20int arr[] = {10, 20, 30, 40, 50};
int *p = arr; // Points to arr[0]
p++; // Moves to arr[1] (increments by sizeof(int))
int val = *p; // val = 20
p += 2; // Moves to arr[3]
int diff = p - arr; // diff = 3 (number of elements between them)
// Common patterns
for (int *ptr = arr; ptr < arr + 5; ptr++) {
printf("%d ", *ptr); // Print all elements
}int *ptr = NULL; // Null pointer (points to nothing)
if (ptr != NULL) { // Always check before dereferencing
*ptr = 10;
}
void *vptr; // Generic pointer
int x = 42;
vptr = &x; // Can hold any address
int *iptr = (int*)vptr; // Must cast before dereferencing
printf("%d\n", *(int*)vptr); // Cast and dereferenceint x = 10;
int *p = &x;
int **pp = &p; // Pointer to pointer
printf("%d\n", **pp); // 10 (double dereference)
**pp = 20; // Modifies x through double pointerconst int *p1; // Pointer to constant int (can't modify value)
int const *p2; // Same as above
int *const p3 = &x; // Constant pointer (can't change address)
const int *const p4 = &x; // Constant pointer to constant int#include <stdlib.h>
// malloc - allocate memory (uninitialized)
int *arr = (int*)malloc(5 * sizeof(int));
// calloc - allocate and initialize to zero
int *arr2 = (int*)calloc(5, sizeof(int));
// realloc - resize memory block
arr = (int*)realloc(arr, 10 * sizeof(int));
// free - deallocate memory
free(arr);
free(arr2);
// Always check for allocation failure
int *ptr = (int*)malloc(100 * sizeof(int));
if (ptr == NULL) {
printf("Memory allocation failed!\n");
exit(1);
}// Dynamic array
int size = 10;
int *dynamic_arr = (int*)malloc(size * sizeof(int));
for (int i = 0; i < size; i++) {
dynamic_arr[i] = i * 2;
}
free(dynamic_arr);
dynamic_arr = NULL; // Prevent dangling pointer
// Dynamic 2D array
int rows = 3, cols = 4;
int **matrix = (int**)malloc(rows * sizeof(int*));
for (int i = 0; i < rows; i++) {
matrix[i] = (int*)malloc(cols * sizeof(int));
}
// Access
matrix[1][2] = 42;
// Free 2D array
for (int i = 0; i < rows; i++) {
free(matrix[i]);
}
free(matrix);// Always free dynamically allocated memory
// Set pointers to NULL after freeing
// Use tools like Valgrind to detect leaks// Define structure
struct Person {
char name[50];
int age;
float height;
};
// Declare variables
struct Person person1;
struct Person person2 = {"John", 25, 1.75};
// Access members
strcpy(person1.name, "Alice");
person1.age = 30;
person1.height = 1.68;
printf("Name: %s, Age: %d\n", person1.name, person1.age);struct Point {
int x;
int y;
};
struct Point p1 = {10, 20};
struct Point *ptr = &p1;
// Access through pointer
ptr->x = 30; // Arrow operator
(*ptr).y = 40; // Dereference then dot
// Dynamic allocation of structure
struct Point *dynamic_p = (struct Point*)malloc(sizeof(struct Point));
dynamic_p->x = 100;
dynamic_p->y = 200;
free(dynamic_p);// Nested structures
struct Date {
int day, month, year;
};
struct Employee {
char name[50];
struct Date birth_date; // Nested structure
struct Date hire_date;
};
// Access nested members
struct Employee emp = {"Bob", {15, 6, 1990}, {1, 1, 2020}};
printf("Year: %d\n", emp.birth_date.year);
// Self-referential structure (linked list node)
struct Node {
int data;
struct Node *next; // Pointer to same structure type
};
// Array of structures
struct Student {
char name[50];
int roll_no;
float marks;
};
struct Student class[50]; // Array of 50 students
class[0].roll_no = 1;
strcpy(class[0].name, "Student1");// Compiler may add padding between members
#pragma pack(1) // Disable padding (pack tightly)
struct PackedStruct {
char c; // 1 byte
int i; // 4 bytes
short s; // 2 bytes
}; // Total: 7 bytes (without padding)
#pragma pack() // Restore default alignmentunion Data {
int i;
float f;
char str[20];
};
// Size of union = size of largest member
printf("Union size: %zu\n", sizeof(union Data));
// Only one member can store value at a time
union Data data;
data.i = 10; // Store integer
printf("%d\n", data.i); // Correct
data.f = 3.14; // Now stores float (overwrites integer!)
printf("%f\n", data.f); // Correct
// printf("%d\n", data.i); // Undefined behavior!#include <stdio.h>
#include <string.h>
// Tagged union for type-safe data storage
enum Type { INT, FLOAT, STRING };
struct Variant {
enum Type type;
union {
int i_val;
float f_val;
char s_val[20];
};
};
int main() {
struct Variant var;
// Store integer
var.type = INT;
var.i_val = 42;
// Store float
var.type = FLOAT;
var.f_val = 3.14f;
// Store string
var.type = STRING;
strcpy(var.s_val, "Hello");
return 0;
}// Enum definition
enum Color {
RED, // 0
GREEN, // 1
BLUE // 2
};
// Custom values
enum Status {
SUCCESS = 200,
NOT_FOUND = 404,
SERVER_ERROR = 500
};
// Mixed assignment
enum Days {
MON = 1,
TUE, // 2
WED, // 3
THU = 10,
FRI, // 11
SAT = 20,
SUN // 21
};
// Usage
enum Color my_color = BLUE;
enum Status response = 200;
// Check
if (my_color == BLUE) {
printf("Color is blue\n");
}
// Switch with enum
switch(my_color) {
case RED: printf("Red\n"); break;
case GREEN: printf("Green\n"); break;
case BLUE: printf("Blue\n"); break;
}// Type aliases
typedef unsigned long ulong;
typedef int (*Operation)(int, int); // Function pointer type
// Structure typedef
typedef struct {
int x;
int y;
} Point;
// Instead of 'struct Point p;', you can use:
Point p1 = {10, 20};
// Common patterns
typedef struct Node {
int data;
struct Node *next;
} Node;
typedef unsigned char byte;
typedef char* string;
// Function pointer typedef
typedef int (*CompareFunc)(const void*, const void*);
// Usage examples
ulong big_number = 1000000L;
Point point;
point.x = 5;
point.y = 10;
CompareFunc cmp = strcmp;#include <stdio.h>
FILE *fp;
char buffer[100];
// Opening files
fp = fopen("file.txt", "r"); // Read
fp = fopen("file.txt", "w"); // Write (creates new/overwrites)
fp = fopen("file.txt", "a"); // Append
fp = fopen("file.txt", "r+"); // Read and write
fp = fopen("file.txt", "w+"); // Write and read
fp = fopen("file.txt", "a+"); // Append and read
fp = fopen("file.bin", "rb"); // Binary read
fp = fopen("file.bin", "wb"); // Binary write
// Always check if file opened successfully
if (fp == NULL) {
perror("Error opening file");
return 1;
}// Text mode
// Character by character
char ch = fgetc(fp); // Read character
fputc('A', fp); // Write character
// Line by line
fgets(buffer, 100, fp); // Read line
fputs("Hello\n", fp); // Write string
// Formatted I/O
fprintf(fp, "Name: %s, Age: %d\n", name, age); // Write formatted
fscanf(fp, "%s %d", name, &age); // Read formatted
// Binary mode
int data[5] = {1, 2, 3, 4, 5};
fwrite(data, sizeof(int), 5, fp); // Write binary
int read_data[5];
fread(read_data, sizeof(int), 5, fp); // Read binary
// File positioning
fseek(fp, 0, SEEK_SET); // Beginning
fseek(fp, 0, SEEK_END); // End
fseek(fp, 10, SEEK_CUR); // Current + 10
long pos = ftell(fp); // Current position
rewind(fp); // Go to beginning
// Check end of file
while (!feof(fp)) {
fgets(buffer, 100, fp);
if (!feof(fp)) { // Avoid processing last line twice
printf("%s", buffer);
}
}
// Close file
fclose(fp);#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *fp;
char name[50];
int age;
// Write to file
fp = fopen("data.txt", "w");
if (fp == NULL) {
perror("Error");
return 1;
}
fprintf(fp, "John 25\n");
fprintf(fp, "Alice 30\n");
fclose(fp);
// Read from file
fp = fopen("data.txt", "r");
if (fp == NULL) {
perror("Error");
return 1;
}
while (fscanf(fp, "%s %d", name, &age) == 2) {
printf("Name: %s, Age: %d\n", name, age);
}
fclose(fp);
return 0;
}// File inclusion
#include <stdio.h> // System header
#include "myheader.h" // User header
// Macros
#define PI 3.14159
#define SQUARE(x) ((x)*(x)) // Parameterized macro (note parentheses!)
#define MAX(a,b) ((a) > (b) ? (a) : (b))
// Conditional compilation
#ifdef DEBUG
printf("Debug mode\n");
#endif
#ifndef HEADER_H
#define HEADER_H
// Header content
#endif
#if defined(__linux__)
// Linux-specific code
#elif defined(_WIN32)
// Windows-specific code
#else
// Other platform
#endif
// Other directives
#undef PI // Undefine macro
#error "Error msg" // Generate compilation error
#pragma warning(...) // Compiler-specific
#pragma pack(1) // Structure packing
// Predefined macros
__FILE__ // Current filename
__LINE__ // Current line number
__DATE__ // Compilation date
__TIME__ // Compilation time
__STDC__ // 1 if standard C compliant
// Stringizing and token pasting
#define TO_STRING(x) #x // Converts x to string
#define CONCAT(x, y) x ## y // Concatenates tokens
// Multi-line macro
#define MULTILINE do { \
statement1; \
statement2; \
} while(0)printf(), scanf(), fprintf(), fscanf()
fopen(), fclose(), fread(), fwrite()
fgets(), fputs(), fgetc(), fputc()
fseek(), ftell(), rewind()
sprintf(), sscanf()
remove(), rename()
perror()malloc(), calloc(), realloc(), free()
atoi(), atof(), atol()
strtol(), strtod()
abs(), labs()
rand(), srand()
exit(), abort()
system()
qsort(), bsearch()strlen(), strcpy(), strncpy()
strcat(), strncat()
strcmp(), strncmp()
strchr(), strrchr()
strstr()
strtok() // Tokenize string
memcpy(), memmove()
memset(), memcmp(), memchr()isalpha(), isdigit(), isalnum()
isupper(), islower()
isspace(), isprint()
toupper(), tolower()sin(), cos(), tan()
asin(), acos(), atan()
sqrt(), pow(), exp()
log(), log10()
ceil(), floor(), round()
fabs(), fmod()
M_PI, M_E // Constants (need #define _USE_MATH_DEFINES on Windows)time_t t;
time(&t); // Get current time
ctime(&t); // Convert to string
clock() // Processor time
difftime(t1, t2) // Time difference
struct tm *now = localtime(&t);
now->tm_year + 1900; // Current year
now->tm_mon + 1; // Current month (0-11)assert(condition); // Program aborts if condition is false
// Compile with -DNDEBUG to disable assertions#include <stdarg.h>
int sum(int count, ...) {
va_list args;
va_start(args, count);
int total = 0;
for (int i = 0; i < count; i++) {
total += va_arg(args, int);
}
va_end(args);
return total;
}
// Usage: sum(3, 10, 20, 30);- Always initialize pointers to NULL
- Check return value of malloc/calloc
- Free dynamically allocated memory
- Set pointer to NULL after free
- Avoid memory leaks - use tools like Valgrind
// 1. Buffer overflow
char buf[10];
gets(buf); // DANGEROUS! Use fgets instead
// 2. Off-by-one errors
int arr[10];
arr[10] = 5; // ERROR: Index 0-9 only
// 3. Uninitialized variables
int x;
printf("%d", x); // Undefined behavior
// 4. Integer division
float result = 5 / 2; // result = 2.0, not 2.5!
float correct = 5.0 / 2; // result = 2.5
// 5. Missing break in switch
// 6. = instead of == in conditions
if (x = 5) // Assignment, not comparison!#define DEBUG(x) printf("Debug: %s = %d\n", #x, x)
int main() {
int value = 42;
DEBUG(value); // Prints: Debug: value = 42
return 0;
}