C Programming Cheatsheet: Syntax, Pointers, and Memory Management
A comprehensive cheatsheet for the C programming language. This guide covers the compilation process, primitive data types, control flow, function design, pointer arithmetic, manual memory management (stack vs. heap), structs, and low-level file I/O operations.
Programming
Contents11 sections
1
Program Structure and Compilation
Understanding the anatomy of a C program and the build process
basics
The Compilation Pipeline: C is a compiled language. Source code (.c) goes through preprocessing (handling macros and includes), compilation (assembly generation), and linking (combining object files and libraries) to produce an executable. The entry point of every C program is the main() function. Preprocessor directives, such as #include, signal the compiler to include standard libraries like stdio.h for input/output operations before compilation begins.
c
// Basic C Program Structure#include<stdio.h>// Preprocessor directive// Function prototype (optional if defined before usage)voiddisplay_message();// Main entry pointintmain(){// Single-line comment/* Multi-line
comment */printf(
bash
// Compilation Commands (GCC)// Compile and link to create executable 'app'// gcc source.c -o app
// Execute
// ./app
2
Data Types and Storage Classes
Primitives, modifiers, and variable scope
types
Type System: C is statically typed. Variables must be declared with a specific type before use. The size of these types (e.g., int, long) is platform-dependent. Modifiers like unsigned, const, and static alter the range, mutability, or storage duration of variables. volatile is used to tell the compiler not to optimize access to a variable, often used in embedded systems or hardware interfacing.
c
// Primitive Typesint id =100;// Integerfloat salary =5000.50f;// Single-precision float
3
Input/Output and Format Specifiers
Handling stdin and stdout streams
io
Standard I/O: Input and output in C are handled via streams. The printf and scanf functions from stdio.h are used for formatted output and input, respectively. Format specifiers act as placeholders that tell the function how to interpret the data (e.g., as an integer, string, or hexadecimal value). Security Note: scanf can be dangerous due to buffer overflows; distinct care must be taken with string inputs.
c
// Format Specifiers// %d or %i : Integer// %f : Float// %lf : Double// %c : Character// %s : String// %p : Pointer address// %x : Hexadecimalint age
4
Control Flow
Conditionals and iteration constructs
control-flow
Logic Flow: C provides standard control structures. The if-else block handles conditional branching, while switch is optimized for checking a single variable against multiple constant integral values. Loops (for, while, do-while) handle iteration. break exits the immediate loop or switch, while continue skips the current iteration and jumps to the loop condition check.
c
// If-Elseif(score >90){ grade ='A';}elseif
5
Arrays and Strings
Contiguous memory allocation and null-terminated strings
arrays
Arrays: An array is a collection of elements of the same type stored in contiguous memory locations. C does not perform bounds checking; accessing an index outside the declared size leads to undefined behavior. Strings in C are simply one-dimensional arrays of characters terminated by a null character \0. Functions in string.h are used to manipulate these character arrays.
c
// Array Declarationint numbers[5]={10,20,30,40,
6
Pointers and Memory Addressing
Direct memory manipulation and pointer arithmetic
pointers
Pointers: A pointer is a variable that stores the memory address of another variable. They are fundamental to C for dynamic memory allocation, array manipulation, and passing large data structures to functions efficiently (by reference). The & operator retrieves an address, while the * operator dereferences an address to access the value stored there. Pointer arithmetic allows navigation through contiguous memory blocks like arrays.
c
// Pointer Syntaxint val =42;int*ptr =&val;// ptr holds the address of val// Dereferencing
7
Functions and Scope
Modularizing code and pass-by-reference
functions
Functions: C functions allow code reuse and modularity. Arguments are passed by value by default (a copy is made). To modify the original variable in the calling function, you must pass the address of the variable (pass by reference via pointers). Scope determines the visibility of variables; local variables exist only within the block they are defined in, while global variables are accessible throughout the program (unless shadowed).
c
// Pass by Valuevoidadd_one(int n){ n++;// Only modifies local copy}// Pass by Reference (using Pointers)
8
Memory Management (Stack vs Heap)
Dynamic memory allocation with malloc and free
memory
Dynamic Allocation: Automatic variables are stored on the Stack and cleaned up automatically. For data that must persist beyond a function call or has a size determined at runtime, C uses the Heap via stdlib.h functions. malloc allocates raw bytes, calloc allocates and zeroes memory, and realloc resizes an existing block. Every allocation must be paired with free to prevent memory leaks.
Structs: Structures allow grouping variables of different types under a single name. They are essential for modeling complex data objects. Unions allow storing different data types in the same memory location (mutually exclusive). Enums define a set of named integer constants for code readability. typedef is frequently used to create aliases for these types to avoid repetitive typing of the struct keyword.
c
// Struct DefinitionstructPoint{int x;int y;};// Typedef for cleaner syntax
10
File Input/Output
Reading from and writing to files
files
File Operations: C uses FILE pointers to handle file streams. Common operations include fopen (open file), fprintf (write formatted text), fscanf (read formatted text), fgets (read string), and fclose (close file). File modes include "r" (read), "w" (write/overwrite), "a" (append), and binary modes like "rb" or "wb". Always check if the file pointer is NULL after opening to ensure the file exists or permission was granted.
c
// Writing to a fileFILE *fp =fopen("data.txt","w");// Open for writingif(
11
Preprocessor Directives
Macros and conditional compilation
preprocessor
The Preprocessor: Before compilation, the preprocessor handles directives starting with #. #define creates constants or macros (text substitution). #ifdef, #ifndef, and #endif are used for conditional compilation, often to prevent header files from being included multiple times (include guards).
c
// Constants#defineMAX_BUFFER1024#definePI3.14159// Macros (Text substitution - use parenthesis carefully)#define
"Hello, World!\n"
)
;
// Standard Output
display_message
(
)
;
return
0
;
// Exit status 0 indicates success
}
void
display_message
(
)
{
printf
(
"C is a procedural language.\n"
)
;
}
double
precise
=
5000.5055
;
// Double-precision float
char
grade
=
'A'
;
// Single character (ASCII)
// Modifiers
unsigned
int
positive_only
=
400
;
// No negative values
long
long
big_number
=
123456789LL
;
const
float
PI
=
3.14159
;
// Read-only variable
// Storage Classes
// static: Preserves value between function calls, limits scope to file
static
int
internal_counter
=
0
;
// extern: Declares a variable defined in another translation unit
extern
int
shared_global
;
c
// Sizeof Operator// Returns the size in bytes of a type or variablesize_t int_size =sizeof(int);// Typically 4 bytes on 32/64-bit systems
;
float
height
;
printf
(
"Enter age and height: "
)
;
// Note: &age passes the address of age to scanf
scanf
(
"%d %f"
,
&
age
,
&
height
)
;
printf
(
"Age: %d, Height: %.2f\n"
,
age
,
height
)
;
(
score
>
80
)
{
grade
=
'B'
;
}
else
{
grade
=
'C'
;
}
// Ternary Operator
int
max
=
(
a
>
b
)
?
a
:
b
;
// Switch Statement
switch
(
option
)
{
case
1
:
start_process
(
)
;
break
;
// Crucial to prevent fall-through
case
2
:
stop_process
(
)
;
break
;
default
:
printf
(
"Invalid option"
)
;
}
c
// For Loop (Initialization; Condition; Increment)for(int i =0; i <10; i++){printf("%d ", i);}// While Loopwhile(active){process_data();if(error_detected) active =0;}// Do-While (Guarantees execution at least once)do{ input =read_sensor();}while(input < threshold);
50
}
;
numbers
[
0
]
=
15
;
// Modification
// Multi-dimensional Array
int
matrix
[
3
]
[
3
]
=
{
{
1
,
0
,
0
}
,
{
0
,
1
,
0
}
,
{
0
,
0
,
1
}
}
;
// Strings (Null-terminated)
char
name
[
6
]
=
{
'H'
,
'e'
,
'l'
,
'l'
,
'o'
,
'\0'
}
;
char
city
[
]
=
"New York"
;
// Compiler adds \0 automatically
// String Functions (<string.h>)
#
include
<string.h>
size_t
len
=
strlen
(
city
)
;
// Length excluding \0
char
dest
[
20
]
;
strcpy
(
dest
,
city
)
;
// Copy string
strcat
(
dest
,
" City"
)
;
// Concatenate
int
result
=
strcmp
(
city
,
"Paris"
)
;
// Compare (0 if equal)
printf
(
"Value: %d"
,
*
ptr
)
;
// Prints 42
*
ptr
=
100
;
// Changes 'val' to 100
// Pointer Arithmetic
int
arr
[
]
=
{
10
,
20
,
30
}
;
int
*
p
=
arr
;
// Points to arr[0]
p
++
;
// Moves to next integer (arr[1])
printf
(
"%d"
,
*
p
)
;
// Prints 20
// Null Pointer
int
*
safe_ptr
=
NULL
;
// Initialize to avoid garbage values
c
// Pointers to Pointersint**double_ptr =&ptr;// Holds address of ptr// Void Pointers (Generic)void*generic_ptr;// Cannot be dereferenced directly; must be cast firstint value =*(int*)generic_ptr;
void
add_one_ref
(
int
*
n
)
{
(
*
n
)
++
;
// Modifies the value at the address
}
int
main
(
)
{
int
x
=
5
;
add_one
(
x
)
;
// x is still 5
add_one_ref
(
&
x
)
;
// x becomes 6
}
// Function Pointers
// Used for callbacks and dynamic function calls
int
(
*
func_ptr
)
(
int
,
int
)
;
func_ptr
=
&
add_numbers
;
// Assume add_numbers exists
int
result
=
func_ptr
(
5
,
10
)
;
malloc
(
5
*
sizeof
(
int
)
)
;
if
(
arr
==
NULL
)
{
// Handle allocation failure
}
// Calloc: Allocate and initialize to zero
int
*
clean_arr
=
(
int
*
)
calloc
(
5
,
sizeof
(
int
)
)
;
// Realloc: Resize existing block
arr
=
(
int
*
)
realloc
(
arr
,
10
*
sizeof
(
int
)
)
;
// Accessing dynamic memory
arr
[
0
]
=
50
;
// Free: Release memory back to OS
free
(
arr
)
;
free
(
clean_arr
)
;
// Dangling Pointer prevention
arr
=
NULL
;
typedef
struct
{
char
name
[
50
]
;
int
id
;
float
gpa
;
}
Student
;
// Usage
struct
Point
p1
=
{
10
,
20
}
;
Student s1
;
// Accessing members
s1
.
id
=
101
;
strcpy
(
s1
.
name
,
"Alice"
)
;
// Pointers to Structs
Student
*
s_ptr
=
&
s1
;
// Arrow operator -> dereferences and accesses member