Structs, Pointers, Memory & File I/O
The size of a struct isn't just the sum of its parts. The compiler adds invisible bytes called **padding** to align members in memory for faster access.
Consider this struct on a 32-bit system:
struct contact {
char name[30];
int phone;
char email[30];
};
Memory Breakdown
name[30]: 30 bytesint on a 4-byte boundary)phone: 4 bytesemail[30]: 30 bytesTotal Size = 30 + 2 + 4 + 30 + 2 = 68 bytes
Factors that can change a struct's size include:
How you pass variables to functions determines if the original value can be changed.
Pass-by-Value: The function gets a copy of the data. Changes inside the function do not affect the original variable. (Used for y below).
Pass-by-Reference: The function gets the memory address (a pointer) of the data. Changes made via the pointer do affect the original variable. (Used for x below).
// x is passed by reference (a pointer)
// y is passed by value (a copy)
void func(int *x, int y) {
// This changes the ORIGINAL x in main()
*x = *x + y;
// This only changes the LOCAL copy of y
y = 2;
}
void main() {
int x = 10, y = 10;
// Pass the address of x, and a copy of y
func(&x, y);
// Output: x: 20, y: 10
printf("x: %d, y: %d", x, y);
}
Pointer Pitfall!
Inside func, be careful about the difference:
*x = 20; — Changes the value at the original address. (Affects main's x).x = 20; — Changes where the local pointer `x` is pointing. (Does NOT affect main's x).A data structure where elements (nodes) are linked together using pointers.
Use the arrow operator -> to traverse from one node to the next.
// Given a pointer 'head' to the first node...
// Access the name of the 2nd node
head->next->name;
// Access the name of the 3rd node
head->next->next->name;
To print a list without losing the reference to the start, use a temporary pointer.
struct Terminal *temp = head; // Create a copy of the head pointer
// Loop while the CURRENT node is not NULL
while (temp != NULL) {
printf("%s", temp->name);
temp = temp->next; // Move the temp pointer, not head
}
// After the loop, 'head' still points to the start of the list!
A three-step process is required to avoid memory leaks.
struct Terminal *temp = head; // 1. Save a reference to the node to be deleted.
head = head->next; // 2. Move head to the next node.
free(temp); // 3. Free the memory of the original first node.
Interacting with files on the disk.
Binary Files: Store raw bytes, exactly as they are in memory. Most space-efficient and fastest for storing data like arrays of structs.
Text Files: Store human-readable characters. Less space-efficient due to conversion overhead (e.g., the number `12345` takes 5 bytes as text vs. 4 bytes as a binary `int`).
The I/O buffer is a temporary memory space to make file operations faster.
fopen(): Opens a file and **creates the buffer**.fread() / fwrite(): **Use** the buffer to read/write data in chunks.fclose(): Flushes any remaining data from the buffer and then **frees the buffer**.Formatted input like scanf() or cin >> var leaves the newline character (`\n`) in the input buffer. This can cause unformatted input functions like gets() or getline() to fail.
int age;
scanf("%d", &age);
// FIX: Clear the leftover '\n' from the buffer
// In C:
while(getchar() != '\n');
// In C++:
std::cin.ignore(std::numeric_limits<std::streamsize>>::max(), '\n');
// Now this will work as expected
gets(fullName);
Pointer
A variable that stores the memory address of another variable.
Dereference
Using the `*` operator on a pointer to access or modify the value stored at the address it's pointing to.
Memory Alignment
The way data is arranged in memory on specific address boundaries for optimal performance. This is why padding is needed.
Padding
Unused bytes added by the compiler inside a struct to ensure its members are properly aligned in memory.
Side Effect
A function has a side effect if it modifies some state outside its local environment, like changing a global variable or a variable passed by reference. In our list example, modifying `head` was an unwanted side effect.
NULL
A special value used for pointers to indicate that they aren't pointing to any valid memory address. Often represented as 0.
free()
A standard library function in C used to deallocate memory that was previously allocated with `malloc`, `calloc`, or `realloc`, preventing memory leaks.