Programming in C

Pointers, Structures, and Unions


Concise notes on pointers, pointer arithmetic, pointers with arrays/strings/functions/structures, and user-defined aggregate types (structures and unions) with essential examples and common pitfalls.


Pointers — Basics

  • Pointer variable stores address of another variable. Example declaration: int *p;.
  • Initialization: assign address: p = &x;.
  • Dereference: access value: *p (value at address).
  • Pointer arithmetic: adding 1 advances by size of pointed type: p + 1.
Pointer example
int x = 10;
int *p = &x;
printf("%d
", *p); // prints 10
*p = 20; // modifies x
pointer-basics

Pointers with Arrays and Strings

  • Arrays and pointers: array name decays to pointer to first element: a ~ &a[0].
  • Access via pointer: *(a + i) equals a[i].
  • Strings: are character arrays; pointers to chars can traverse strings.
  • Pointer types: type of pointer determines arithmetic increment size.
Array access via pointer
int a[5] = {1,2,3,4,5};
int *p = a; // points to a[0]
int x = *(p + 2); // x == a[2] == 3

Pointers and Functions

  • Pointers as arguments: to modify caller data pass pointer: void set(int *p).
  • Functions returning pointers: return pointer to dynamically allocated memory or static data; avoid returning pointer to local stack variable.
  • Pointers and functions: use pointers to pass large data (arrays, structures) efficiently.
Function modifies caller via pointer
void inc(int *p) { (*p)++; }

int x = 5;
inc(&x); // x becomes 6

Pointers and Structures

  • Structure access via pointer: use -> operator: p->field when p is struct pointer.
  • Passing structures: pass pointer to structure for efficiency: void f(struct S *p).
  • Functions returning pointers to structures: return dynamically allocated structure pointers with care.
Structure pointer example
struct Point { int x, y; };
struct Point p = {1,2};
struct Point *pp = &p;
printf("%d
", pp->x);

Structures

  • Definition: aggregate user-defined type: struct S { int a; float b; };
  • Declaration/initialization: struct S s = {1, 2.5};
  • Array of structures: struct S arr[10];
  • Size and alignment: depends on member types and padding; use sizeof to know size.
  • Nested structures: structure can contain another structure as a member.
  • Self-referential structures: used for linked lists: struct Node { int val; struct Node *next; };
Structure example
struct Student {
  char name[30];
  int id;
  float gpa;
};

struct Student s = {"Alex", 101, 8.5};
printf("%s
", s.name);
struct-memory

Unions

  • Union: a data type where all members share the same memory location. Declaration: union U { int i; float f; };
  • Size: size of union equals size of its largest member.
  • Use cases: memory-efficient variants, type punning (careful), embedded systems.
  • Access: use dot or arrow similar to structures.
Union example
union Number {
  int i;
  float f;
};

union Number n;
n.i = 10;
n.f = 2.5; // overwrites same memory
union-layout

Debugging Exercise

Find and fix the errors
#include <stdio.h>
#include <stdlib.h>

int *make_array(int n) {
  int a[n]; // local VLA on stack
  for (int i = 0; i < n; i++) a[i] = i;
  return a; // error: returning address of stack memory
}
Correct points
  • Do not return pointer to local stack array. Allocate with malloc and return pointer, or pass buffer from caller.
  • Always check result of malloc for NULL.

Programming Exercise

  • Implement linked list insert/delete using self-referential structures and pointers.
  • Create a function that returns a dynamically allocated array (use malloc) and document proper ownership and free semantics.