Pointers and Arrays in C: Decay, Indexing and Worked Examples
Separate arrays from pointers with runnable traces covering indexing, one-past boundaries, function parameters, two-dimensional arrays and declaration traps.
KnowledgeGate Team
Exam prep & CS education

a[i], *(a + i) and p[i] can reach the same element, yet an array and a pointer are not the same object. Arrays and Pointers in C: Complete Guide with Worked Examples for GATE and Interviews owns the first-pass memory model, 2D address arithmetic and *p++ precedence. The harder handoff is between expression types: indexed mutation, array-parameter decay and row-pointer stepping. Predict each output or address before reading its trace, then check who owns the storage, what type the expression has and which element the offset reaches.
Pointers and arrays in C: one memory picture
Start with int a[5] = {12, 7, 25, 4, 18};. The array owns five contiguous int elements indexed 0 through 4. In int *p = a;, a converts to a pointer to a[0], so p == &a[0].
The separate variable p stores that address and can later point elsewhere. The array name cannot be reassigned or incremented. An array is not a pointer.
![Memory map of int a[5] = {12, 7, 25, 4, 18} with a and p at a[0], p + 2 at 25, and a + 5 marked as one-past.](https://cdn.knowledgegate.ai/blog-assets/blog_asset_1784449827829_dyn7sk.jpg)
Array indexing and pointer arithmetic: a runnable trace
#include <stdio.h>
int main(void) {
int a[5] = {12, 7, 25, 4, 18};
int *p = a;
printf("%d %d %d\n", a[2], *(a + 2), p[2]);
p[3] = p[0] + a[1];
for (int i = 0; i < 5; ++i) {
printf("%d%c", a[i], i == 4 ? '\n' : ' ');
}
return 0;
}The exact output is:
25 25 25
12 7 25 19 18For a valid index, x[i] means *(x + i), so all three expressions reach a[2]. Next, p[0] is 12 and a[1] is 7, giving p[3] = 12 + 7 = 19. Since p[3] is a[3], the fourth value changes from 4 to 19.
With the diagram's four-byte int and base address 1000, p + 3 is 1000 + 3 * 4 = 1012. Pointer subtraction reports elements: &a[4] - &a[1] == 3, not 12 bytes. Forming a + 5 for comparison is valid; dereferencing it is undefined behaviour.
Array-to-pointer decay: where conversion stops
Expression | Type or meaning | Result in this example |
|---|---|---|
| Converts to | Points at |
|
| Points at |
| Whole-array size | Five elements |
| One- | One element |
|
| Points at the whole array |
In the declaring scope, sizeof a / sizeof a[0] == 5. Under the four-byte assumption, that is 20 / 4 = 5. sizeof p is sizeof(int *).
a = p; and a++ are invalid because a is not modifiable. p = &a[2]; validly makes *p == 25. Arrays and Strings in C: Array-to-Pointer Decay, sizeof Traps and 2D Address Arithmetic owns string sentinels, a versus &a and full row-major address derivation. Function calls add a different contract: the caller owns the array, while the parameter receives only a pointer view.
Passing an array to a function needs a length
#include <stddef.h>
#include <stdio.h>
int sum(const int values[], size_t n) {
int total = 0;
for (size_t i = 0; i < n; ++i) {
total += values[i];
}
return total;
}
int main(void) {
int values[] = {3, 5, 8, 13};
size_t n = sizeof values / sizeof values[0];
printf("%d\n", sum(values, n));
return 0;
}The caller gets n = 4. The running total is 0 -> 3 -> 8 -> 16 -> 29, so the output is 29. The call supplies a pointer to values[0]; no array copy occurs.
In a parameter list, const int values[] adjusts to const int *values. Thus a sizeof ratio inside sum uses the pointer size and cannot recover the count. Pass n; const prevents changes through values.
Pointer to an array versus array of pointers
Parentheses decide the declaration. int (*row)[3] is one pointer to an array of three integers; int *refs[2] is an array of two pointers.
For int matrix[2][3] = {{2, 4, 6}, {1, 3, 5}}; int (*row)[3] = matrix;, row[0][1] == 4 and *(*(row + 1) + 2) == 5. With four-byte integers and illustrative base 2000, a row is 3 * 4 = 12 bytes, so row + 1 is 2000 + 12 = 2012.
For int x = 7, y = 11; int *refs[2] = {&x, &y};, refs owns two pointer elements and *refs[1] == 11. The row pointer steps by a complete row; refs indexes separate pointers.

Common pointer-and-array errors and repairs
Faulty idea | Why it happens | What goes wrong | Repair |
|---|---|---|---|
|
| Undefined behaviour | Point it at a live object |
Loop while | Index confused with length | Access at index 5 | Use |
| One-past can be formed | One-past dereference | Stop before it |
| Array treated as pointer variable | Array is not modifiable | Increment a pointer |
| Matrix treated as flat | Type is | Use |
Parameter length from | Brackets resemble an array | Parameter is a pointer | Pass the count |
Returning a pointer to local int local[3] also leaves a dangling pointer. Let the caller own the destination array and pass its pointer plus length.
How exams and interviews test pointers with arrays
Three checks that come up repeatedly, with answers:
int b[] = {4, 9, 16, 25}; int *q = b + 1;followed byprintf("%d %d\n", *q, *(q + 2));prints9 25.int (*q)[4]is a pointer to an array of four integers.int *q[4]is an array of four integer pointers.A numeric value for
sizeof q, whenqis a pointer, needs implementation information.
Reverse the array with two valid pointers:
int main(void) {
int b[5] = {2, 4, 6, 8, 10};
int *left = b, *right = b + 4;
while (left < right) {
int temp = *left;
*left++ = *right;
*right-- = temp;
}
return 0;
}The states are {10, 4, 6, 8, 2}, then {10, 8, 6, 4, 2}. The middle 6 stays unchanged.
Typical tasks cover output tracing, index translation, one-past boundaries, parameter sizeof and declarations. They sit inside CS Fundamentals for Exams & Placements; solve the three checks above from types and bounds rather than guessing a machine's pointer size.
Pointers and arrays in C: the short version and next step
An array owns contiguous element storage.
Most array expressions convert to a pointer to the first element.
For valid indexing,
x[i]means*(x + i).Pointer arithmetic scales by the pointed-to type.
A one-past pointer may be formed but not dereferenced.
The three traces agree: p[3] changes 4 to 19; the sum is 29; and row + 1 reaches illustrative address 2012. Storage, type and offset explain all three.
Compile both programs with warnings, redraw the first diagram, then change a[2] from 25 to 30. Predict 30 30 30 first while a[3] still becomes 19. Continue with the C Language Course: Concepts, MCQs & Coding Questions for structured concepts and practice.
Keep learning

Functions in C: Syntax, Parameters and Worked Examples
Learn how C declarations, calls, and definitions fit together. Compile two complete programs, follow their values, and trace composition and recursion.

Smart Pointers in C++: unique_ptr, shared_ptr and weak_ptr with Worked Examples
Learn who owns a C++ object, when it is destroyed, and how to choose among unique_ptr, shared_ptr, weak_ptr and a borrowed raw pointer.

Pointers in C: Addresses, Arrays and Functions with Worked Examples
Build a practical pointer model with runnable C programs for dereferencing, arrays, swapping, dynamic memory and common tracing questions.

Function Pointers in C: Declarations, Callbacks and Runnable Examples
Learn to read function-pointer declarations, build a callback dispatch table, guard invalid selections, and write a safe qsort comparator in C.