Back to blog
Backend Systemsbeginner

C Functions, Structs & Arrays

Master C functions, parameter passing, structs, typedef, and arrays. Learn how C organizes code and data before introducing pointers.

Asma HafeezApril 17, 20265 min read
cfunctionsstructsarraystypedef
Share:𝕏

C Functions, Structs & Arrays

Functions let you organize code into reusable units. Structs let you group related data together. Together they're the building blocks of C programs before you reach pointers.


Functions

C
#include <stdio.h>

// Declaration (prototype) — tells the compiler the function exists
int add(int a, int b);

// Definition
int add(int a, int b) {
    return a + b;
}

// Void function — returns nothing
void greet(const char* name) {
    printf("Hello, %s!\n", name);
}

int main(void) {
    int result = add(3, 4);    // 7
    greet("Alice");             // Hello, Alice!
    return 0;
}

Pass by Value

C passes arguments by value — the function gets a copy.

C
void double_it(int n) {
    n = n * 2;  // modifies the local copy only
}

int x = 5;
double_it(x);
printf("%d\n", x);  // 5 — unchanged!

To modify the original, use pointers (covered in the next lesson).


Function Prototypes

Declare functions before main or in a header file.

C
// math_utils.h — header file
#ifndef MATH_UTILS_H
#define MATH_UTILS_H

int    max(int a, int b);
double power(double base, int exp);
int    is_prime(int n);

#endif
C
// math_utils.c — implementation
#include "math_utils.h"

int max(int a, int b) { return a > b ? a : b; }

double power(double base, int exp) {
    double result = 1.0;
    for (int i = 0; i < exp; i++) result *= base;
    return result;
}

int is_prime(int n) {
    if (n < 2) return 0;
    for (int i = 2; i * i <= n; i++) {
        if (n % i == 0) return 0;
    }
    return 1;
}

Structs — Group Related Data

C
// Define a struct type
struct Point {
    double x;
    double y;
};

// Use it
struct Point p1;
p1.x = 3.0;
p1.y = 4.0;

// Initialize with a literal
struct Point p2 = {6.0, 8.0};
struct Point origin = {.x = 0.0, .y = 0.0};  // designated initializers

// Access members
printf("(%f, %f)\n", p1.x, p1.y);

typedef — Cleaner Syntax

C
typedef struct {
    double x;
    double y;
} Point;  // now use just "Point" instead of "struct Point"

Point p = {3.0, 4.0};

// Functions with structs (passed by value — copy)
double distance(Point a, Point b) {
    double dx = a.x - b.x;
    double dy = a.y - b.y;
    return sqrt(dx * dx + dy * dy);  // #include <math.h>
}

double d = distance(p, origin);

Nested Structs

C
typedef struct {
    char   first[50];
    char   last[50];
} Name;

typedef struct {
    Name   name;
    int    age;
    double salary;
} Employee;

Employee emp = {
    .name   = {.first = "Alice", .last = "Smith"},
    .age    = 30,
    .salary = 85000.0
};

printf("Name: %s %s, Age: %d\n",
    emp.name.first, emp.name.last, emp.age);

Arrays of Structs

C
#define MAX_STUDENTS 100

typedef struct {
    char   name[50];
    int    id;
    double gpa;
} Student;

Student class[MAX_STUDENTS];
int count = 0;

// Add students
void add_student(const char* name, int id, double gpa) {
    if (count >= MAX_STUDENTS) return;
    // strncpy is safer than strcpy
    strncpy(class[count].name, name, sizeof(class[count].name) - 1);
    class[count].name[sizeof(class[count].name) - 1] = '\0';
    class[count].id  = id;
    class[count].gpa = gpa;
    count++;
}

// Print all students
void print_students(void) {
    for (int i = 0; i < count; i++) {
        printf("ID: %d | %-20s | GPA: %.2f\n",
            class[i].id, class[i].name, class[i].gpa);
    }
}

// Find student by ID
int find_student(int id) {
    for (int i = 0; i < count; i++) {
        if (class[i].id == id) return i;  // return index
    }
    return -1;  // not found
}

Variable-Length Logic with Arrays

C
// Compute sum and average of an array
double sum_array(const double* arr, int n) {
    double total = 0.0;
    for (int i = 0; i < n; i++) {
        total += arr[i];
    }
    return total;
}

double average(const double* arr, int n) {
    if (n == 0) return 0.0;
    return sum_array(arr, n) / n;
}

// Bubble sort
void sort_int_array(int* arr, int n) {
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                int temp   = arr[j];
                arr[j]     = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

double grades[] = {85.5, 92.0, 78.3, 90.0, 88.5};
int n = sizeof(grades) / sizeof(grades[0]);
printf("Average: %.2f\n", average(grades, n));

Enums

C
typedef enum {
    PENDING,
    ACTIVE,
    INACTIVE,
    DELETED
} AccountStatus;

typedef struct {
    int           id;
    char          owner[50];
    double        balance;
    AccountStatus status;
} Account;

const char* status_to_string(AccountStatus s) {
    switch (s) {
        case PENDING:  return "Pending";
        case ACTIVE:   return "Active";
        case INACTIVE: return "Inactive";
        case DELETED:  return "Deleted";
        default:       return "Unknown";
    }
}

Account acc = {1, "Alice", 1000.0, ACTIVE};
printf("Account #%d (%s): $%.2f [%s]\n",
    acc.id, acc.owner, acc.balance, status_to_string(acc.status));

Function Pointers

C
// A function pointer type: int (*fn)(int, int)
typedef int (*BinaryOp)(int, int);

int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
int mul(int a, int b) { return a * b; }

// Apply any operation
int apply(BinaryOp op, int x, int y) {
    return op(x, y);
}

printf("%d\n", apply(add, 3, 4));  // 7
printf("%d\n", apply(mul, 3, 4));  // 12

// Array of function pointers (dispatch table)
BinaryOp ops[] = {add, sub, mul};
const char* names[] = {"add", "sub", "mul"};
for (int i = 0; i < 3; i++) {
    printf("%s(10, 3) = %d\n", names[i], ops[i](10, 3));
}

Key Takeaways

  1. C passes arguments by value — functions receive copies; use pointers to modify originals
  2. Always use header guards (#ifndef) in .h files to prevent double-inclusion
  3. typedef struct removes the need to write struct every time
  4. Pass the length alongside arrays to functions — arrays don't carry their size
  5. Function pointers enable polymorphism and callbacks in C — essential for sorting and event systems

Enjoyed this article?

Explore the Backend Systems learning path for more.

Found this helpful?

Share:𝕏

Leave a comment

Have a question, correction, or just found this helpful? Leave a note below.