C Programming Cheat Sheet

Structs, Pointers, Memory & File I/O

Structs & Memory Alignment

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.

Calculating Struct Size

Consider this struct on a 32-bit system:

struct contact {
    char name[30];
    int  phone;
    char email[30];
};

Memory Breakdown

  • name[30]: 30 bytes
  • Padding: 2 bytes (to align int on a 4-byte boundary)
  • phone: 4 bytes
  • email[30]: 30 bytes
  • Padding: 2 bytes (to make total size a multiple of 4)

Total Size = 30 + 2 + 4 + 30 + 2 = 68 bytes

Factors that can change a struct's size include:

Pointers & Functions

How you pass variables to functions determines if the original value can be changed.

Pass-by-Value vs. Pass-by-Reference

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).

Linked Lists

A data structure where elements (nodes) are linked together using pointers.

Accessing Nodes

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;

Safe Traversal (No Side Effects)

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!

Deleting the First Node

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.

File I/O

Interacting with files on the disk.

File Types

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`).

File Operations & Buffering

The I/O buffer is a temporary memory space to make file operations faster.

Handling Mixed Input

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);

Glossary of Terms

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.