Mastering C Pointers: From Memory Basics to Advanced Usage
This comprehensive guide explains the fundamentals of pointers in C, covering memory layout, variable storage, address arithmetic, const and void pointers, pointer arrays, function pointers, and common pitfalls, with clear diagrams and runnable code examples to deepen your understanding of low‑level programming.
Introduction
The article begins by stating that pointers are the most powerful and complex concept in C, offering high efficiency when used correctly but also introducing many pitfalls.
Variables and the Essence of Pointers
When a program is compiled, the executable is stored on disk as a static file. At launch the operating system loads the code and data sections into memory, creates a process control block, and sets the CPU to start executing at the entry point. The loaded program becomes a dynamic process.
Copy program sections from disk to memory. Create a PCB describing resources, file descriptors, etc. Jump to the entry function address.
Memory is treated uniformly as virtual memory; the OS maps virtual addresses to physical pages.
32‑bit vs 64‑bit Systems
CPU register width determines the address bus width and thus the maximum addressable space. An 8‑bit address bus can address 256 bytes, a 32‑bit bus 4 GB, while a 64‑bit bus can address astronomically larger spaces. Real systems use paging, segmentation, and other techniques beyond this simple model.
Variables
Variables are concrete storage locations identified by names. The name is an abstract symbol; the compiler maps it to a concrete address in memory. Example: int a = 20; The variable a occupies four bytes (on a typical 32‑bit system) at address 0x11223344. The address‑of operator & yields this address: printf("&a = 0x%x \n", &a); Output: &a = 0x11223344.
Pointer Variables
A pointer variable is itself a variable that stores the address of another object. Its type indicates the type of the pointed‑to data. In a 32‑bit system a pointer occupies 4 bytes because addresses are 32 bits long.
int a = 20;
int *pa;
pa = &a;
printf("value = %d
", *pa);The memory model shows pa stored at 0x11223348 with the value 0x11223344, the address of a.
Operators
& – address‑of operator, yields the address of a variable. * – dereference operator, used both in a declaration ( int *p; ) and to read the value stored at the pointed address.
Operations on Pointers
Manipulate the pointer’s own value (e.g., increment, assign).
Access the data the pointer refers to.
Interpret the pointed data according to the pointer’s type.
Pointer Value
int a = 20;
printf("a = %d
", a);
a = 100;Pointer Dereference
printf("pa = %d
", pa);
pa = &a;Address of a Pointer
printf("&pa = 0x%x
", &pa);Result: &pa = 0x11223348.
Const Pointers
constcan qualify either the pointer itself or the data it points to.
int a = 20;
int * const p = &a; // pointer is constant, value can changeAttempting p = &b; is a compile‑time error, while *p = 21; is allowed.
const int *p = &a; // data is constant, pointer can change
p = &b; // OKVoid Pointers
void *is a generic pointer type that can hold the address of any object without specifying its type. It cannot be dereferenced directly; it must be cast to a concrete pointer type first.
int a = 20;
int *p1 = &a;
void *p2 = p1; // OK
int *p3 = (int *)p2; // cast back before useStandard library functions such as memcpy(void *dest, const void *src, size_t len) use void * to accept any data type.
Pointer Arrays and Array Pointers
Two commonly confused declarations:
int *p1[3]; // array of 3 int pointers
int (*p2)[3]; // pointer to an array of 3 intsFor p1, each element is a separate pointer; for p2, the pointer refers to a contiguous block of three int elements. Incrementing p2 advances by the size of the whole array (12 bytes on a 32‑bit system).
Multidimensional Arrays and Pointers
int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
int (*p0)[3] = a[0];
printf("0: %d %d %d
", *(*p0+0), *(*p0+1), *(*p0+2));The pointer arithmetic works on whole rows because p0 points to an array of three int s.
Structure Pointers
typedef struct {int age; char name[8];} Student;
Student s;
s.age = 20;
strcpy(s.name, "lisi");
Student *p = &s;
printf("age = %d, name = %s
", p->age, p->name);When iterating over an array of structures, p++ moves by sizeof(Student) bytes (12 bytes in the example).
Function Pointers
A function pointer stores the address of a function and can be invoked like a regular function.
int add(int x,int y){return x+y;}
int (*p)(int,int) = add;
printf("%d + %d = %d
", 1,2, p(1,2));Function signatures must match. For many functions, a typedef simplifies declarations:
typedef int (*pFunc)(int,int);
pFunc p1, p2;Function Pointer Arrays
int add(int a,int b){return a+b;}
int sub(int a,int b){return a-b;}
int (*p[4])(int,int) = {add, sub, mul, divide};
printf("%d + %d = %d
", a,b, p[0](a,b));The array holds addresses of several functions, allowing selection at runtime.
Key Takeaways
Pointer = address, address = pointer. The type of a pointer determines how the pointed memory is interpreted.
Understanding the memory model and how pointers map names to addresses is essential for mastering C and any low‑level programming.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
