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
Pointers with Arrays and Strings
- Arrays and pointers: array name decays to pointer to first element:
a~&a[0]. - Access via pointer:
*(a + i)equalsa[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] == 3Pointers 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 6Pointers and Structures
- Structure access via pointer: use
->operator:p->fieldwhenpisstructpointer. - 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
sizeofto 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);
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
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
mallocand return pointer, or pass buffer from caller. - Always check result of
mallocforNULL.
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.