To manage large projects, declarations are often placed in header files (.h) and implemented in source files (.c). To prevent a header from being processed multiple times, which would cause errors, you must use inclusion guards:
#ifndef UTILS_H
#define UTILS_H
int add(int a, int b);
#endif
Control Flow: Conditions and Loops
Logic in C is driven by Boolean expressions using relational operators (<,>,≤,≥,==,=) and logical operators ($&&, ||, !$).
- Conditions: Use
if/else for branching and switch for multiple discrete values. Be careful: = is an assignment, while == is a comparison.
- Loops: Use
for loops for count-controlled repetition (like iterating through an array), while loops for condition-based repetition, and do-while loops when the body must execute at least once.
Arrays and Memory Management
Arrays are fixed-size, homogeneous, and contiguous blocks of memory. Because indexing starts at 0, an array of size N has valid indices from 0 to N−1; accessing arr[N] is an "out of bounds" error.
You can use the sizeof operator to calculate the number of elements in a local array by dividing the total bytes of the array by the bytes of one element:
count=sizeof(array[0])sizeof(array)
However, be warned: when an array is passed to a function, it "decays" into a pointer, and this sizeof trick will no longer return the original array length.
Common Mistake: When traversing an array with a loop, never use i <= size. Always use i < size to avoid accessing memory outside the array bounds.
Pointers and Parameter Passing
Pointers are one of the most critical concepts in C. A pointer stores a memory address. You use the & (address-of) operator to get an address and the * (dereference) operator to access the value stored at that address.
A helpful mental shortcut is:
& = WHERE is the variable?
* = WHAT IS THERE at that address?
Pass by Value vs. Pass by Pointer
By default, C uses pass by value, meaning the function receives a copy of the data. To allow a function to modify the original variable in the caller's scope, you must use output parameters by passing the address of the variable using & and receiving it as a pointer.
void setValue(int *out) { *out = 100; } // Function definition
int x = 5;
setValue(&x); // Function call: x is now 100
Strings and File I/O
In C, a string is simply a char array that ends with the null terminator '\0'. You should use the <string.h> library for manipulations:
strlen: Get length.
strcpy: Copy one string to another.
strcat: Append (join) strings.
strcmp: Compare strings (returns 0 if they are equal).
For persistent data, use File Streams via the FILE * type. The standard workflow is: Open (fopen), Check for NULL, Operate (fscanf/fprintf or fgets/fputs), and Close (fclose).
Compilation, Linking, and Debugging
The process of turning code into a running program involves several steps:
- Source Code: Your human-readable
.c files.
- Object Code: Machine code produced by the compiler (e.g., using
gcc -c file.c to create file.o).
- Executable: The final program created by the linker, which combines object files and libraries.
A typical gcc command to compile and link multiple files is:
gcc main.c utils.c -o program.
Debugging Checklist
When your code doesn't work, check for these common issues:
- Compiler Errors: Syntax mistakes that stop the build.
- Warnings: Suspicious code (use
gcc -Wall to see them).
- Logic Errors: The program runs but gives the wrong answer (e.g., using
= instead of ==).
- Memory Errors: Dereferencing a
NULL pointer or accessing an array out of bounds.
Final Study Priority: Focus your remaining time on arrays, loops, pointer memory diagrams, and the difference between & and *.