Skip to content
| Marketplace
Sign in
Visual Studio Code>Other>Testing Random StuffNew to Visual Studio Code? Get it now.
Testing Random Stuff

Testing Random Stuff

pepepopo

| (0) | Free
This extension does nothing. It just exists.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

C Programming Reference Guide

Quick reference notes for C programming concepts commonly used in exams.


1. Makefiles

What is a Makefile?

A file that tells make how to compile your project automatically.

Windows Reminder

  • Use: mingw32-make
  • Executables must end in: .exe

Makefile Rule Format

target: dependencies
	gcc command

⚠️ Commands must start with a TAB, not spaces.

Single-File Makefile

build:
	gcc main.c -o main.exe

Multi-File Makefile

Most exam tasks use this pattern:

program.exe: main.o utils.o
	gcc main.o utils.o -o program.exe

main.o: main.c utils.h
	gcc -c main.c

utils.o: utils.c utils.h
	gcc -c utils.c

clean:
	del *.o program.exe

Benefits:

  • Only rebuilds files that changed
  • clean target removes generated files

Makefile with Rebuild

rebuild: clean program.exe

Using Variables

CC = gcc
CFLAGS = -Wall -c

program.exe: main.o item.o
	$(CC) main.o item.o -o program.exe

main.o:
	$(CC) $(CFLAGS) main.c

Makefile Exam Worksheet Example

You must be able to build programs such as:

1️⃣ Program that prints the smaller of two numbers
2️⃣ Program that prints the average of all numbers in command-line args
3️⃣ Create a Makefile that builds both

Example Makefile:

all: smaller average

smaller: smaller.o
	gcc smaller.o -o smaller.exe

average: average.o
	gcc average.o -o average.exe

smaller.o: smaller.c
	gcc -c smaller.c

average.o: average.c
	gcc -c average.c

clean:
	del *.o *.exe

2. Structs (Explained from Zero)

A struct is a custom data type that groups different variables together.

Basic Declaration

struct Person {
    char name[20];
    int age;
    float height;
};

This defines a new type that has 3 members.

How to Declare a Struct Variable

struct Person p1;

How to Access Members

p1.age = 20;
p1.height = 1.80;
strcpy(p1.name, "Jonathan");

Using typedef (Renaming a Struct)

Instead of always typing struct Person, use:

typedef struct Person {
    char name[20];
    int age;
} Person;

Then you can simply write:

Person p1;

Dynamic Structs (Very Important for Exam)

Person *p = malloc(sizeof(Person));

p->age = 20;
strcpy(p->name, "John");

free(p);

✅ Use -> when accessing members via pointer.

Bitfields (Memory-Saving Technique)

Used when storing many YES/NO or small numeric values:

struct Flags {
    unsigned int a : 1;  // uses 1 bit
    unsigned int b : 1;
    unsigned int c : 1;
};

Now the struct might only use 1 byte instead of 12 bytes.


3. Unions (Explained from Zero)

A union allows multiple fields, but only one can exist at a time. All fields share the same memory.

Basic Declaration

union Data {
    int i;
    float f;
    char str[20];
};

Understanding Union Memory

  • i uses 4 bytes
  • f uses 4 bytes
  • str[20] uses 20 bytes

The union's size = 20 bytes (the largest member)

All fields share these same 20 bytes of memory:

 --------------------
| 20 bytes shared    |
 --------------------

Example: How Memory Overlaps

union Data data;

data.i = 15;      // stores int in shared memory
data.f = 3.14;    // overwrites the int - value is now garbage

When Unions are Useful

  • When storing different types, but only one at a time
  • To save memory (embedded systems, sensors, message protocols)
  • When interpreting raw memory in different formats

4. Struct + Union + Enum (Exam Worksheet - VERY IMPORTANT)

This is an extremely exam-likely pattern. You must be able to build a message handler that uses all three concepts together.

Required Structure

enum MessageType { ERROR, TEMPERATURE, TEXT };

union MessageData {
    int errorCode;
    float temperature;
    char text[50];
};

struct Message {
    enum MessageType type;
    union MessageData data;
};

What You Must Do

  • Store messages (array version + dynamic version)
  • Accept user input from a menu
  • Display all stored messages

Complete Example (Array Version)

#include <stdio.h>
#include <string.h>

enum MessageType { ERROR, TEMPERATURE, TEXT };

union MessageData {
    int errorCode;
    float temperature;
    char text[50];
};

struct Message {
    enum MessageType type;
    union MessageData data;
};

int main() {
    struct Message messages[10];
    int count = 0;
    int choice;

    while (1) {
        printf("\nMessage Handler Menu\n");
        printf("1. Enter error message\n");
        printf("2. Enter temperature\n");
        printf("3. Enter text\n");
        printf("4. Display all\n");
        printf("5. Exit\n");
        scanf("%d", &choice);

        if (choice == 1) {
            printf("Enter error code: ");
            scanf("%d", &messages[count].data.errorCode);
            messages[count].type = ERROR;
            count++;
        }

        else if (choice == 2) {
            printf("Enter temperature: ");
            scanf("%f", &messages[count].data.temperature);
            messages[count].type = TEMPERATURE;
            count++;
        }

        else if (choice == 3) {
            printf("Enter message: ");
            scanf(" %[^\n]", messages[count].data.text);
            messages[count].type = TEXT;
            count++;
        }

        else if (choice == 4) {
            for (int i=0; i<count; i++) {
                if (messages[i].type == ERROR)
                    printf("Error: %d\n", messages[i].data.errorCode);
                else if (messages[i].type == TEMPERATURE)
                    printf("Temperature: %.2f\n", messages[i].data.temperature);
                else if (messages[i].type == TEXT)
                    printf("Text: %s\n", messages[i].data.text);
            }
        }

        else if (choice == 5) break;
    }

    return 0;
}

Dynamic Version (Linked List)

This matches the linked list pattern perfectly:

struct Node {
    struct Message msg;
    struct Node *next;
};

Allocate:

struct Node* n = malloc(sizeof(struct Node));

Access:

n->msg.type = TEXT;
strcpy(n->msg.data.text, "hello");

6. Menu Loop Template

Useful for union/struct exam programs:

while (1) {
    printf("1. Add\n2. Show\n3. Exit\n");
    scanf("%d", &choice);

    if (choice == 1) {
        // add
    }
    else if (choice == 2) {
        // display
    }
    else break;
}

7. Command Line Arguments

Count Arguments

int main(int argc, char *argv[]) {
    printf("Args: %d\n", argc);
}

Find Smaller of Two Arguments

int a = atoi(argv[1]);
int b = atoi(argv[2]);
printf("Smaller = %d\n", (a < b ? a : b));

Average of All Arguments

float sum = 0;

for (int i = 1; i < argc; i++)
    sum += atof(argv[i]);

printf("Avg = %.2f\n", sum / (argc - 1));

8. Perfect Exam Template (Makefile + Program)

Makefile

program.exe: main.o message.o
	gcc main.o message.o -o program.exe

main.o: main.c message.h
	gcc -c main.c

message.o: message.c message.h
	gcc -c message.c

clean:
	del *.o program.exe

Message Handler Makefile Example

program.exe: main.o message.o
	gcc main.o message.o -o program.exe

main.o: main.c message.h
	gcc -c main.c

message.o: message.c message.h
	gcc -c message.c

clean:
	del *.o program.exe

9. Quick Reference Summary

Structs

  • Use . for normal struct access
  • Use -> for pointer access
  • Dynamic: malloc(sizeof(Type))

Unions

  • Share memory
  • Only one field valid at a time
  • Size = largest field

Makefiles

  • Use TAB, not spaces
  • Windows executables end in .exe
  • Multi-file compilation uses .o files

Enums

enum Type { ERROR, TEMP, TEXT };

10. Practical Examples

Example 1: Finding the Smaller Number

C Program

#include <stdio.h>
#include <stdlib.h> // Needed for atoi (convert string to int)

// argc = argument count (how many words in a command line)
// argv = argument vector (array of strings holding the words)
int main(int argc, char *argv[]){
    // We expect 3 things: the program name, num1, and num2
    // e.g., "./smaller 10 20" -> argc is 3
    if(argc != 3){
        printf("Error: Please provide exactly 2 numbers.\n");
        printf("Usage: ./smaller <num1> <num2>\n");
        return 1;
    }

    // Convert strings (argv) to integers
    int num1 = atoi(argv[1]);
    int num2 = atoi(argv[2]);

    if (num1 < num2){
        printf("Smaller: %d\n", num1);
    }
    else{
        printf("Smaller: %d\n", num2);
    }
    return 0;
}

Makefile

# Target 1: The smaller number program
smaller: smaller.c
	gcc -Wall -o smaller.exe smaller.c

# Target 2: clean
clean:
	del smaller.exe

How to use:

./smaller 10 20    # Output: Smaller: 10
./smaller 50 30    # Output: Smaller: 30

Example 2: BMI Calculator

C Program

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    // 1. Check if we have enough ingredients
    // (Program name + Weight + Height = 3)
    if (argc != 3) {
        printf("Error: Missing values.\n");
        printf("Usage: ./bmi <weight_kg> <height_m>\n");
        return 1;
    }

    // 2. Parse data. atof converts string to float.
    double weight = atof(argv[1]);
    double height = atof(argv[2]);

    // 3. Validation (Don't divide by zero or allow negative height!)
    if (height <= 0 || weight <= 0) {
        printf("Error: Invalid height or weight.\n");
        return 1;
    }

    // 4. The Math
    double bmi = weight / (height * height);

    // 5. The Vibe Check (Categories)
    printf("Your BMI is: %.2f\n", bmi);
    printf("Category: ");

    if (bmi < 18.5) {
        printf("Underweight\n");
    } else if (bmi >= 18.5 && bmi <= 24.9) {
        printf("Normal\n");
    } else if (bmi >= 25 && bmi <= 29.9) {
        printf("Overweight\n");
    } else {
        printf("Obese\n");
    }

    return 0;
}

Makefile

bmi: bmi.c
	gcc -Wall -o bmi.exe bmi.c

clean:
	del bmi.exe

How to use:

./bmi 70 1.75      # Output: BMI with category
./bmi 85 1.80      # Output: BMI with category

Key Concepts Demonstrated:

  • Command-line argument parsing with argc and argv
  • String to number conversion (atoi for int, atof for float)
  • Input validation
  • Conditional logic for categorization
  • Makefile targets for building and cleaning

Example 3: Vehicle Fleet Manager (Multi-File Project)

This is a complete multi-file project demonstrating:

  • Header files (.h)
  • Multiple source files (.c)
  • Struct + Union + Enum pattern
  • Multi-file compilation with Makefile

vehicle.h (Header File)

#ifndef VEHICLE_H
#define VEHICLE_H

// 1. The Tag: Tells us which version of the union we are using
// "Variant data" logic from your notes
typedef enum {
    CAR,
    TRUCK
} VehicleType;

// 2. The Union: Shares memory. Only ONE of these exists at a time.
// Size = size of largest member (float weight)
typedef union {
    int passengers;   // Used if type is CAR
    float weight;     // Used if type is TRUCK
} VehicleData;

// 3. The Struct: Wraps it all together
struct Vehicle {
    VehicleType type;     // The "Tag"
    VehicleData data;     // The "Payload"
    char model[20];       // Common data for everyone
};

// Function Prototypes
void print_vehicle(struct Vehicle v);

#endif

main.c (Main Program)

#include <stdio.h>
#include <string.h>
#include "vehicle.h"

int main() {
    struct Vehicle myFleet[2]; // Array of structs

    // Vehicle 1: A Car
    // We access members using the dot operator (.)
    myFleet[0].type = CAR;
    strcpy(myFleet[0].model, "Toyota Prius");
    myFleet[0].data.passengers = 5;

    // Vehicle 2: A Truck
    // Note: We overwrite the SAME memory space 'data', but now as a float
    myFleet[1].type = TRUCK;
    strcpy(myFleet[1].model, "Ford F-150");
    myFleet[1].data.weight = 2.5;

    // Print them out
    for (int i = 0; i < 2; i++) {
        print_vehicle(myFleet[i]);
    }

    return 0;
}

vehicle.c (Implementation)

#include <stdio.h>
#include <string.h>
#include "vehicle.h"

void print_vehicle(struct Vehicle v) {
    printf("Model: %s\n", v.model);
    
    if (v.type == CAR) {
        printf("Type: Car\n");
        printf("Passengers: %d\n\n", v.data.passengers);
    } else if (v.type == TRUCK) {
        printf("Type: Truck\n");
        printf("Weight: %.2f tons\n\n", v.data.weight);
    }
}

Makefile

# Default target - builds the final executable
# Note: Windows executable has .exe extension
all: fleet.exe

# Link object files to create the executable
fleet.exe: main.o vehicle.o
	gcc -Wall -g -o fleet.exe main.o vehicle.o

# Compile main.c -> main.o
# Dependency: main.c AND vehicle.h (if header changes, we rebuild)
main.o: main.c vehicle.h
	gcc -Wall -g -c main.c -o main.o

# Compile vehicle.c -> vehicle.o
vehicle.o: vehicle.c vehicle.h
	gcc -Wall -g -c vehicle.c -o vehicle.o

# Clean up (Windows specific)
# Uses 'del' instead of 'rm' because you are on Windows CMD
clean:
	del fleet.exe main.o vehicle.o

How to use:

make              # Builds fleet.exe
./fleet.exe       # Runs the program
make clean        # Removes built files

Expected Output:

Model: Toyota Prius
Type: Car
Passengers: 5

Model: Ford F-150
Type: Truck
Weight: 2.50 tons

Key Concepts Demonstrated:

  • Header guards (#ifndef, #define, #endif)
  • Function prototypes in header file
  • Multiple source files compiled separately
  • Enum for type tagging
  • Union for variant data (passengers vs. weight)
  • Struct combining enum + union
  • Makefile dependencies (rebuilding when headers change)
  • Code organization - interface vs. implementation

NOTES

/*Struct: Struct has a seperate section for each item, eg: Lunchbox for Rice, meat, and veggies. Memory: Each item gets its own space. SYNTAX:

struct Student{ int id; float gpa; char name[20];
}; //Size = Dize of (int + float + char array) = BIG

Unions: Union is a single box that can hold ONE thing at a time. Memory: All members share the same memory location. The size of the union is just the size of the LARGEST item inside. SYNTAX:

union MessageData{ int errorCode; // 4 bytes float temperature; //4 bytes char text[50]; // 50 bytes }; // Total Size of Union = 50 bytes (Size of the largest member)

*/

/* Makefiles:

The Syntax: Makefiles USE TABS NOT SPACES.

Structure: Target: Dependencies Command (MUST be a TAB indent, not spaces!)

  • Target: The file you want to create (e.g program.exe)
  • Dependencies: The files needed to create the target (e.g., main.c)
  • Command: The terminal command to build it (e.g. gcc ...)

*/

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2025 Microsoft