Back to Subjects
C Cheatsheet
Comprehensive C programming guide with syntax, pointers, memory management, and system programming.
C Programming Cheatsheet
Basic Syntax
Hello World
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
Basic Structure
#include <stdio.h> // Standard input/output
#include <stdlib.h> // Standard library
#include <string.h> // String functions
// Function declaration
int add(int a, int b);
int main() {
// Main function - entry point
return 0;
}
// Function definition
int add(int a, int b) {
return a + b;
}
Data Types
Basic Data Types
// Integer types
char c = 'A'; // 1 byte
short s = 32767; // 2 bytes
int i = 2147483647; // 4 bytes
long l = 9223372036854775807L; // 8 bytes
// Unsigned versions
unsigned char uc = 255;
unsigned short us = 65535;
unsigned int ui = 4294967295U;
unsigned long ul = 18446744073709551615UL;
// Floating point
float f = 3.14f; // 4 bytes
double d = 3.14159; // 8 bytes
long double ld = 3.141592653589793L; // 16 bytes
// Size information
printf("char: %zu bytes\n", sizeof(char));
printf("int: %zu bytes\n", sizeof(int));
printf("float: %zu bytes\n", sizeof(float));
printf("double: %zu bytes\n", sizeof(double));
Constants and Literals
// Preprocessor constants
#define PI 3.14159
#define MAX_SIZE 100
// const keyword
const int DAYS_IN_WEEK = 7;
const char* MESSAGE = "Hello";
// Literal examples
int decimal = 42; // Decimal
int octal = 052; // Octal (starts with 0)
int hex = 0x2A; // Hexadecimal (starts with 0x)
float scientific = 1.23e-4f; // Scientific notation
// Character escape sequences
char newline = '\n';
char tab = '\t';
char backslash = '\\';
char quote = '\"';
Variables and Storage Classes
Variable Declaration
int x; // Declaration
int y = 10; // Declaration with initialization
int a, b, c; // Multiple declarations
int d = 1, e = 2; // Multiple with initialization
// Automatic variables (local)
void function() {
auto int local_var = 10; // 'auto' is default
int another_local = 20; // Same as above
}
// Static variables
void counter() {
static int count = 0; // Retains value between calls
count++;
printf("Count: %d\n", count);
}
// External variables (global)
extern int global_var; // Declaration (defined elsewhere)
int global_var = 100; // Definition
// Register variables (suggestion to compiler)
void fast_function() {
register int fast_var = 42; // May be stored in CPU register
}
Operators
Arithmetic Operators
int a = 10, b = 3;
int addition = a + b; // 13
int subtraction = a - b; // 7
int multiplication = a * b; // 30
int division = a / b; // 3 (integer division)
int modulo = a % b; // 1
// Increment/Decrement
int x = 5;
printf("%d\n", ++x); // Pre-increment: 6
printf("%d\n", x++); // Post-increment: 6 (then x becomes 7)
printf("%d\n", --x); // Pre-decrement: 6
printf("%d\n", x--); // Post-decrement: 6 (then x becomes 5)
Comparison and Logical Operators
int a = 10, b = 20;
// Comparison operators
int equal = (a == b); // 0 (false)
int not_equal = (a != b); // 1 (true)
int less_than = (a < b); // 1 (true)
int greater_than = (a > b); // 0 (false)
int less_equal = (a <= b); // 1 (true)
int greater_equal = (a >= b); // 0 (false)
// Logical operators
int and_result = (a > 5) && (b < 30); // 1 (true)
int or_result = (a > 15) || (b < 30); // 1 (true)
int not_result = !(a > 15); // 1 (true)
Bitwise Operators
int a = 12; // Binary: 1100
int b = 10; // Binary: 1010
int and_op = a & b; // 8 (1000)
int or_op = a | b; // 14 (1110)
int xor_op = a ^ b; // 6 (0110)
int not_op = ~a; // -13 (complement)
int left_shift = a << 1; // 24 (11000)
int right_shift = a >> 1; // 6 (110)
// Practical bitwise operations
int set_bit = a | (1 << 2); // Set bit at position 2
int clear_bit = a & ~(1 << 2); // Clear bit at position 2
int toggle_bit = a ^ (1 << 2); // Toggle bit at position 2
int check_bit = (a >> 2) & 1; // Check if bit at position 2 is set
Control Flow
Conditional Statements
int x = 10;
// if-else
if (x > 0) {
printf("Positive\n");
} else if (x < 0) {
printf("Negative\n");
} else {
printf("Zero\n");
}
// Ternary operator
int abs_x = (x >= 0) ? x : -x;
printf("Absolute value: %d\n", abs_x);
// switch statement
char grade = 'B';
switch (grade) {
case 'A':
printf("Excellent!\n");
break;
case 'B':
printf("Good job!\n");
break;
case 'C':
printf("Average\n");
break;
default:
printf("Invalid grade\n");
break;
}
Loops
// for loop
for (int i = 0; i < 10; i++) {
printf("%d ", i);
}
printf("\n");
// while loop
int count = 0;
while (count < 5) {
printf("Count: %d\n", count);
count++;
}
// do-while loop
int input;
do {
printf("Enter a positive number: ");
scanf("%d", &input);
} while (input <= 0);
// Nested loops
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
printf("(%d,%d) ", i, j);
}
printf("\n");
}
// Loop control
for (int i = 0; i < 10; i++) {
if (i == 3) continue; // Skip iteration
if (i == 7) break; // Exit loop
printf("%d ", i);
}
Functions
Basic Functions
// Function declaration (prototype)
int add(int a, int b);
void greet(const char* name);
double calculate_area(double radius);
// Function definitions
int add(int a, int b) {
return a + b;
}
void greet(const char* name) {
printf("Hello, %s!\n", name);
}
double calculate_area(double radius) {
return 3.14159 * radius * radius;
}
// Function calls
int main() {
int sum = add(5, 3);
greet("Alice");
double area = calculate_area(2.5);
return 0;
}
Advanced Function Features
// Recursive function
int factorial(int n) {
if (n <= 1) {
return 1;
}
return n * factorial(n - 1);
}
// Function with variable arguments
#include <stdarg.h>
int sum_all(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_all(3, 10, 20, 30) returns 60
// Function pointers
int (*operation)(int, int); // Declare function pointer
int multiply(int a, int b) {
return a * b;
}
int main() {
operation = add;
printf("Add: %d\n", operation(5, 3));
operation = multiply;
printf("Multiply: %d\n", operation(5, 3));
return 0;
}
Arrays
One-Dimensional Arrays
// Array declaration and initialization
int numbers[5]; // Uninitialized array
int scores[5] = {85, 92, 78, 96, 88}; // Initialized array
int values[] = {1, 2, 3, 4, 5}; // Size inferred from initializer
int zeros[10] = {0}; // Initialize all elements to 0
// Array access and modification
scores[0] = 90; // Modify first element
int first_score = scores[0]; // Access first element
// Array traversal
for (int i = 0; i < 5; i++) {
printf("Score %d: %d\n", i, scores[i]);
}
// Array size
int size = sizeof(scores) / sizeof(scores[0]);
printf("Array size: %d\n", size);
Multi-Dimensional Arrays
// 2D array declaration and initialization
int matrix[3][4]; // 3x4 matrix
int grid[3][3] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// Alternative initialization
int table[2][3] = {{1, 2, 3}, {4, 5, 6}};
// 2D array access
grid[1][2] = 10; // Set element at row 1, column 2
int value = grid[2][1]; // Get element at row 2, column 1
// 2D array traversal
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
printf("%d ", grid[i][j]);
}
printf("\n");
}
// 3D array
int cube[2][3][4]; // 2x3x4 three-dimensional array
Arrays and Functions
// Passing array to function (array decays to pointer)
void print_array(int arr[], int size) {
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
// Alternative syntax
void print_array2(int* arr, int size) {
// Same as above
}
// Passing 2D array to function
void print_matrix(int rows, int cols, int matrix[rows][cols]) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%d ", matrix[i][j]);
}
printf("\n");
}
}
// Using arrays
int main() {
int numbers[] = {1, 2, 3, 4, 5};
int size = sizeof(numbers) / sizeof(numbers[0]);
print_array(numbers, size);
int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}};
print_matrix(2, 3, matrix);
return 0;
}
Pointers
Basic Pointers
int x = 42;
int* ptr = &x; // ptr points to x
printf("Value of x: %d\n", x); // 42
printf("Address of x: %p\n", &x); // Address
printf("Value of ptr: %p\n", ptr); // Same address
printf("Value pointed by ptr: %d\n", *ptr); // 42
// Modify value through pointer
*ptr = 100;
printf("New value of x: %d\n", x); // 100
Pointer Arithmetic
int arr[] = {10, 20, 30, 40, 50};
int* p = arr; // Points to first element
printf("First element: %d\n", *p); // 10
printf("Second element: %d\n", *(p + 1)); // 20
printf("Third element: %d\n", *(p + 2)); // 30
// Moving pointer
p++; // Now points to second element
printf("Current element: %d\n", *p); // 20
// Pointer difference
int* start = &arr[0];
int* end = &arr[4];
int distance = end - start; // 4 (elements apart)
// Array traversal using pointers
for (int* ptr = arr; ptr < arr + 5; ptr++) {
printf("%d ", *ptr);
}
Dynamic Memory Allocation
#include <stdlib.h>
// Allocate memory for single integer
int* num = (int*)malloc(sizeof(int));
if (num != NULL) {
*num = 42;
printf("Dynamic value: %d\n", *num);
free(num); // Don't forget to free!
}
// Allocate memory for array
int size = 10;
int* arr = (int*)malloc(size * sizeof(int));
if (arr != NULL) {
// Initialize array
for (int i = 0; i < size; i++) {
arr[i] = i * i;
}
// Use array
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
// Resize array
size = 20;
arr = (int*)realloc(arr, size * sizeof(int));
free(arr); // Free memory
}
// calloc - allocates and initializes to zero
int* zeros = (int*)calloc(10, sizeof(int));
if (zeros != NULL) {
// All elements are initialized to 0
free(zeros);
}
Pointers to Pointers
int x = 42;
int* ptr = &x;
int** ptr_to_ptr = &ptr;
printf("Value: %d\n", **ptr_to_ptr); // 42
printf("Address of ptr: %p\n", ptr_to_ptr);
printf("Value of ptr: %p\n", *ptr_to_ptr);
// Dynamic 2D array using pointer to pointer
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));
}
// Use matrix
matrix[1][2] = 100;
// Free matrix
for (int i = 0; i < rows; i++) {
free(matrix[i]);
}
free(matrix);
Strings
String Basics
#include <string.h>
// String declaration and initialization
char str1[20] = "Hello"; // Character array
char str2[] = "World"; // Size inferred
char* str3 = "Hello, World!"; // String literal (read-only)
// String input/output
char name[50];
printf("Enter your name: ");
scanf("%s", name); // Reads until whitespace
printf("Hello, %s!\n", name);
// Reading line with spaces
char line[100];
printf("Enter a line: ");
getchar(); // Clear newline from buffer
fgets(line, sizeof(line), stdin); // Reads entire line
printf("You entered: %s", line);
String Functions
#include <string.h>
char str1[50] = "Hello";
char str2[50] = "World";
char str3[100];
// String length
int len = strlen(str1); // 5
// String copy
strcpy(str3, str1); // str3 = "Hello"
strncpy(str3, str1, 3); // str3 = "Hel"
// String concatenation
strcat(str1, " "); // str1 = "Hello "
strcat(str1, str2); // str1 = "Hello World"
strncat(str3, str2, 2); // Append first 2 chars
// String comparison
int cmp = strcmp(str1, str2); // Returns 0 if equal
int ncmp = strncmp(str1, str2, 3); // Compare first 3 chars
// String search
char* pos = strchr(str1, 'o'); // Find first occurrence of 'o'
char* last = strrchr(str1, 'o'); // Find last occurrence of 'o'
char* sub = strstr(str1, "World"); // Find substring
// String to number conversion
char num_str[] = "12345";
int num = atoi(num_str); // String to integer
double dnum = atof("123.45"); // String to double
// Number to string conversion
char buffer[20];
sprintf(buffer, "%d", 12345); // Integer to string
sprintf(buffer, "%.2f", 123.45); // Double to string with format
String Manipulation
// Custom string functions
int my_strlen(const char* str) {
int length = 0;
while (str[length] != '\0') {
length++;
}
return length;
}
void my_strcpy(char* dest, const char* src) {
int i = 0;
while (src[i] != '\0') {
dest[i] = src[i];
i++;
}
dest[i] = '\0';
}
// String reversal
void reverse_string(char* str) {
int len = strlen(str);
for (int i = 0; i < len / 2; i++) {
char temp = str[i];
str[i] = str[len - 1 - i];
str[len - 1 - i] = temp;
}
}
// Character classification
#include <ctype.h>
char ch = 'A';
printf("Is digit: %d\n", isdigit(ch)); // 0
printf("Is alpha: %d\n", isalpha(ch)); // 1
printf("Is upper: %d\n", isupper(ch)); // 1
printf("Is lower: %d\n", islower(ch)); // 0
printf("To lower: %c\n", tolower(ch)); // 'a'
printf("To upper: %c\n", toupper('a')); // 'A'
Structures
Basic Structures
// Structure definition
struct Person {
char name[50];
int age;
float height;
};
// Structure variable declaration
struct Person person1;
struct Person person2 = {"John Doe", 30, 5.9};
// Accessing structure members
strcpy(person1.name, "Jane Smith");
person1.age = 25;
person1.height = 5.6;
printf("Name: %s\n", person1.name);
printf("Age: %d\n", person1.age);
printf("Height: %.1f\n", person1.height);
// Array of structures
struct Person people[3] = {
{"Alice", 28, 5.4},
{"Bob", 32, 6.0},
{"Charlie", 29, 5.8}
};
// Accessing array of structures
for (int i = 0; i < 3; i++) {
printf("Person %d: %s, Age: %d\n", i + 1, people[i].name, people[i].age);
}
Pointers to Structures
struct Person* ptr = &person1;
// Accessing members through pointer
(*ptr).age = 26; // Method 1
ptr->age = 26; // Method 2 (preferred)
strcpy(ptr->name, "Jane Doe");
// Dynamic allocation of structures
struct Person* dynamic_person = (struct Person*)malloc(sizeof(struct Person));
if (dynamic_person != NULL) {
strcpy(dynamic_person->name, "Dynamic Person");
dynamic_person->age = 35;
dynamic_person->height = 5.7;
printf("Dynamic person: %s\n", dynamic_person->name);
free(dynamic_person);
}
Nested Structures and typedef
// Nested structures
struct Address {
char street[100];
char city[50];
int zip_code;
};
struct Employee {
char name[50];
int id;
struct Address address;
float salary;
};
// Using nested structure
struct Employee emp;
strcpy(emp.name, "John Smith");
emp.id = 1001;
strcpy(emp.address.street, "123 Main St");
strcpy(emp.address.city, "Anytown");
emp.address.zip_code = 12345;
emp.salary = 50000.0;
// typedef for easier syntax
typedef struct {
char brand[30];
char model[30];
int year;
float price;
} Car;
// Now we can use Car instead of struct Car
Car my_car = {"Toyota", "Camry", 2022, 25000.0};
Car* car_ptr = &my_car;
printf("Car: %s %s\n", car_ptr->brand, car_ptr->model);
File I/O
Basic File Operations
#include <stdio.h>
// Opening and closing files
FILE* file = fopen("data.txt", "w"); // Open for writing
if (file == NULL) {
printf("Error opening file!\n");
return 1;
}
// Writing to file
fprintf(file, "Hello, File!\n");
fprintf(file, "Number: %d\n", 42);
fputs("This is a line\n", file);
fputc('A', file);
fclose(file); // Always close the file
// Reading from file
file = fopen("data.txt", "r");
if (file != NULL) {
char buffer[100];
// Reading line by line
while (fgets(buffer, sizeof(buffer), file) != NULL) {
printf("Read: %s", buffer);
}
fclose(file);
}
Advanced File Operations
// Binary file operations
struct Person person = {"Alice", 30, 5.6};
// Write binary data
FILE* bin_file = fopen("person.dat", "wb");
if (bin_file != NULL) {
fwrite(&person, sizeof(struct Person), 1, bin_file);
fclose(bin_file);
}
// Read binary data
struct Person read_person;
bin_file = fopen("person.dat", "rb");
if (bin_file != NULL) {
fread(&read_person, sizeof(struct Person), 1, bin_file);
printf("Read person: %s, %d\n", read_person.name, read_person.age);
fclose(bin_file);
}
// File positioning
FILE* file = fopen("data.txt", "r+");
if (file != NULL) {
fseek(file, 0, SEEK_END); // Go to end of file
long size = ftell(file); // Get file size
fseek(file, 0, SEEK_SET); // Go to beginning
// Read specific position
fseek(file, 10, SEEK_SET); // Go to 10th byte
int ch = fgetc(file);
fclose(file);
}
Preprocessor
Macros
// Simple macros
#define PI 3.14159
#define MAX_SIZE 100
#define SQUARE(x) ((x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
// Using macros
double area = PI * SQUARE(5);
int max_val = MAX(10, 20);
// Multi-line macros
#define PRINT_ERROR(msg) \
do { \
printf("Error: %s\n", msg); \
printf("File: %s, Line: %d\n", __FILE__, __LINE__); \
} while(0)
// Conditional compilation
#ifdef DEBUG
printf("Debug mode enabled\n");
#endif
#ifndef BUFFER_SIZE
#define BUFFER_SIZE 1024
#endif
#if defined(WINDOWS)
// Windows-specific code
#elif defined(LINUX)
// Linux-specific code
#else
// Default code
#endif
Include Guards
// header.h
#ifndef HEADER_H
#define HEADER_H
// Header content goes here
void my_function();
#endif // HEADER_H
// Alternative using pragma once
#pragma once
// Header content
Memory Management
Stack vs Heap
void memory_demo() {
// Stack allocation (automatic)
int stack_var = 42; // Automatically freed when function ends
char stack_array[100]; // Fixed size, fast allocation
// Heap allocation (dynamic)
int* heap_var = malloc(sizeof(int));
if (heap_var != NULL) {
*heap_var = 42;
free(heap_var); // Must manually free
}
// Large array on heap
int* large_array = malloc(1000000 * sizeof(int));
if (large_array != NULL) {
// Use array...
free(large_array);
}
}
Memory Debugging
// Check for memory leaks
void check_memory() {
int* ptr1 = malloc(100 * sizeof(int));
int* ptr2 = malloc(200 * sizeof(int));
if (ptr1 != NULL && ptr2 != NULL) {
// Use memory...
free(ptr1);
free(ptr2);
// Set pointers to NULL to avoid accidental use
ptr1 = NULL;
ptr2 = NULL;
}
}
// Safe memory allocation wrapper
void* safe_malloc(size_t size) {
void* ptr = malloc(size);
if (ptr == NULL) {
fprintf(stderr, "Memory allocation failed!\n");
exit(1);
}
return ptr;
}
Common Patterns and Best Practices
Error Handling
#include <errno.h>
// Function with error checking
int safe_divide(int a, int b, int* result) {
if (b == 0) {
return -1; // Error code
}
*result = a / b;
return 0; // Success
}
// File operations with error handling
FILE* safe_fopen(const char* filename, const char* mode) {
FILE* file = fopen(filename, mode);
if (file == NULL) {
perror("Error opening file");
return NULL;
}
return file;
}
// Using error handling
int main() {
int result;
if (safe_divide(10, 0, &result) != 0) {
printf("Division by zero error!\n");
}
FILE* file = safe_fopen("nonexistent.txt", "r");
if (file == NULL) {
printf("Failed to open file\n");
} else {
// Use file...
fclose(file);
}
return 0;
}
Generic Programming with void*
// Generic swap function
void swap(void* a, void* b, size_t size) {
char* temp = malloc(size);
if (temp != NULL) {
memcpy(temp, a, size);
memcpy(a, b, size);
memcpy(b, temp, size);
free(temp);
}
}
// Usage
int x = 10, y = 20;
swap(&x, &y, sizeof(int));
double d1 = 3.14, d2 = 2.71;
swap(&d1, &d2, sizeof(double));
Useful Libraries
Standard Library Functions
#include <math.h>
#include <time.h>
#include <stdlib.h>
// Math functions
double result = sqrt(16.0); // 4.0
double power = pow(2.0, 3.0); // 8.0
double sine = sin(PI / 2); // 1.0
int absolute = abs(-5); // 5
// Random numbers
srand(time(NULL)); // Seed random number generator
int random_num = rand() % 100; // Random number 0-99
double random_double = (double)rand() / RAND_MAX; // 0.0-1.0
// Time functions
time_t current_time = time(NULL);
printf("Current time: %s", ctime(¤t_time));
clock_t start = clock();
// ... some computation ...
clock_t end = clock();
double cpu_time = ((double)(end - start)) / CLOCKS_PER_SEC;
printf("CPU time: %f seconds\n", cpu_time);
Best Practices
- Always initialize variables before using them
- Check return values of functions that can fail
- Free dynamically allocated memory to prevent leaks
- Use const for parameters that shouldn't be modified
- Validate input before processing
- Use meaningful variable names and comments
- Keep functions small and focused on one task
- Avoid global variables when possible
- Use header guards in header files
- Compile with warnings enabled (-Wall -Wextra)