0% found this document useful (0 votes)
2 views8 pages

Pointers in C

The document provides a comprehensive overview of pointers in C, explaining their definition, usage, and various operations such as declaration, dereferencing, and pointer arithmetic. It covers advanced topics like pointer-to-pointer, dynamic memory allocation, and function pointers, along with common pitfalls and practical examples. Key concepts such as memory visualization, arrays, and structs in relation to pointers are also discussed.

Uploaded by

omarsulaiman359
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views8 pages

Pointers in C

The document provides a comprehensive overview of pointers in C, explaining their definition, usage, and various operations such as declaration, dereferencing, and pointer arithmetic. It covers advanced topics like pointer-to-pointer, dynamic memory allocation, and function pointers, along with common pitfalls and practical examples. Key concepts such as memory visualization, arrays, and structs in relation to pointers are also discussed.

Uploaded by

omarsulaiman359
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

Pointers in C

1. What is a Pointer? (Very Simple Explanation)

A pointer is a variable that stores the memory address of another variable.

Example:
If a normal variable stores a value → 10
A pointer stores where that value is kept in memory → like 0x7ffeefb8d9c.

So:

 Normal variable → stores data


 Pointer variable → stores address of data

2. Why Do We Use Pointers?

Pointers are used because they allow us to:

✔ Access memory directly


✔ Share data between functions
✔ Create dynamic memory (malloc/free)
✔ Handle arrays and strings efficiently
✔ Create data structures like Linked List, Tree, Stack, Queue

3. Declaring a Pointer

Syntax:

int *ptr;

Meaning:
ptr is a pointer that can store the address of an int.

4. Storing Address in Pointer

int a = 10;
int *p = &a;

Explanation:

 a stores 10
 &a gives address of a
 p stores that address

Memory Visualization

a = 10
Address of a → 1000
p stores 1000
p → 1000 → 10

5. Dereferencing a Pointer (*)

Dereferencing means accessing the value stored at the pointer’s address.

printf("%d", *p);

*p gives the value → 10

Basic declaration, address, dereference (diagram + example)

Code

#include <stdio.h>

int main() {
int a = 10; // a holds value 10
int *p = &a; // p holds address of a

printf("a = %d\n", a);


printf("&a = %p\n", (void*)&a);
printf("p = %p\n", (void*)p);
printf("*p = %d\n", *p); // value at address stored in p

return 0;
}

Memory diagram (conceptual)

Address Variable Value


--------------------------------
0x1000 a 10
0x2000 p 0x1000 <-- p stores address of a

Visual:

p (0x2000) ---points to---> [ a @0x1000 ] ---> value 10


deref: *p == 10

Key points

• p == &a

• *p reads/writes a's value (*p = 20; sets a = 20).

3. Pointer arithmetic (why it moves by sizeof(type))

Idea

When you increment a pointer p++, it moves by sizeof(*p) bytes (so an int* typically moves by 4
bytes on many systems, double* by 8, char* by 1).

Example

int arr[] = {10, 20, 30};


int *p = arr; // arr == &arr[0]
printf("%d\n", *p); // 10
p++;
printf("%d\n", *p); // 20 (pointer moved to next element)
Diagram

Addresses: 0x1000 0x1004 0x1008


arr[0] 10 20 30
p --> [10] ---> [20] ---> [30]

4. Arrays and pointers — close relationship

• arr (in most expressions) decays to a pointer to the first element &arr[0].

• arr[i] is the same as *(arr + i).

Example: iterate using a pointer

for (int *q = arr; q < arr + 3; q++) {


printf("%d ", *q);
}
This prints 10 20 30.

5. Pointer to pointer (double pointer) — diagrams + example

Code

int a = 5;
int *p = &a; // p -> a
int **pp = &p; // pp -> p -> a

printf("%d\n", **pp); // 5
Diagram

Address Variable Value


--------------------------------
0x1000 a 5
0x2000 p 0x1000
0x3000 pp 0x2000

pp -> p -> a -> 5


*pp == p ; **pp == a's value
Use-cases

• Passing pointer by reference (function modifies caller’s pointer).

• Dynamic arrays of pointers, multi-dimensional arrays represented as pointer-to-pointer.

6. Pointers and functions — call by reference

To let a function change a variable from the caller, pass its pointer.

Swap example

void swap(int *x, int *y) {


int t = *x;
*x = *y;
*y = t;
}

int main() {
int a = 3, b = 7;
swap(&a, &b); // pass addresses
// now a == 7 and b == 3
}
Diagram during swap(&a, &b):

main stack: a->3, b->7


swap receives x->address_of_a, y->address_of_b
*x and *y modify original variables

7. Dynamic memory (malloc/free) — heap vs stack

Key points

• malloc, calloc, realloc allocate memory on the heap; returns pointer.

• free(ptr) releases it.

• Use after allocation: check for NULL (allocation failure).

Example

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

int main() {
int n = 5;
int *p = malloc(n * sizeof *p);
if (!p) { perror("malloc"); return 1; }

for (int i = 0; i < n; i++) p[i] = i * 10;


for (int i = 0; i < n; i++) printf("%d ", p[i]);

free(p); // important
return 0;
}
Diagram

Stack: p (holds address 0x5000)


Heap at 0x5000: [0] [1] [2] [3] [4] (allocated block)
Common errors: forgetting free → memory leak; using freed memory → dangling pointer.

8. Strings & pointers

A C string is char[] ending with '\0'. char *s = "HELLO"; points to string literal (usually read-
only).

Example

char s[] = "HELLO"; // modifiable array on stack


char *t = "WORLD"; // pointer to string literal (don't modify)
printf("%c %c\n", s[1], *(t + 2)); // E, R
Diagram:

Memory:
s -> 'H' 'E' 'L' 'L' 'O' '\0' (modifiable)
t -> "WORLD\0" (in read-only area)

9. Structs and pointers

Pointer to struct is common: struct Node *p; and access via p->member (same as (*p).member).

Example: simple node

struct Node {
int data;
struct Node *next;
};
Diagram for one node

heap block: [ data: 10 | next: 0x0000 ] // a single node with next NULL
pointer head -> that block

10. Function pointers

A pointer can point to a function; useful for callbacks, dispatch tables.

Example

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


int sub(int a, int b) { return a - b; }

int main() {
int (*op)(int,int) = add;
printf("%d\n", op(5,3)); // 8

op = sub;
printf("%d\n", op(5,3)); // 2
}

11. Advanced: pointer casting & void *

• void * is a generic pointer (no type). You can cast to/from void*.

• Use void* with malloc and for APIs that take generic data.

void *vp = malloc(100);


int *ip = (int*) vp;
Prefer int *ip = malloc(100 * sizeof *ip); (no cast in C and safer style).

12. Common pitfalls — illustrated and explained

1 Uninitialized (wild) pointer

int *p; // contains garbage address

*p = 5; // undefined behavior — likely crash

Always initialize: int *p = NULL; or p = &x;.

2 Null pointer dereference

int *p = NULL;

printf("%d", *p); // crash (segfault)

Always check if (p != NULL) before deref.

3 Dangling pointer

int *p = malloc(sizeof *p);

free(p);

printf("%d", *p); // undefined — p is dangling

After free, set p = NULL;.

4 Buffer overflow

Writing past allocated memory corrupts memory:

int *p = malloc(3 * sizeof *p);

p[3] = 10; // out-of-bounds (valid indices 0..2)

5 Memory leak

Losing pointer to heap block without free:

p = malloc(...);

p = malloc(...); // previous block lost => leak


6 Wrong sizeof usage

Use malloc(n * sizeof *p) or malloc(n * sizeof(int)). Do not use sizeof(p) to get element
size — sizeof(p) gives pointer size, not *p.

Practice examples (try/run these)

Example A — Reverse array using pointers

#include <stdio.h>
void reverse(int *a, int n) {
int *l = a, *r = a + n - 1;
while (l < r) {
int t = *l; *l = *r; *r = t;
l++; r--;
}
}
Example B — allocate 2D array dynamically (pointer-to-pointer)

int **mat = malloc(rows * sizeof *mat);


for (i = 0; i < rows; ++i)
mat[i] = malloc(cols * sizeof *mat[i]);
(Remember to free each row then free mat.)

Example C — function pointer usage (simple strategy pattern)

int operate(int (*f)(int,int), int a, int b) { return f(a,b); }

15. Quick reference table

Symbol Meaning
&x address of x
*p value pointed by p
T *p p is pointer to type T
p++ move pointer to next T element (+ sizeof(T) bytes)
NULL pointer that points to nothing
void* untyped pointer (generic)
p->m shorthand for (*p).m when p points to struct

You might also like