An array expression, a pointer and &array can display the same starting address, yet they are not the same type and do not advance by the same amount. That is the source of many C output, type and sizeof traps. Let int a[5] = {12, 7, 25, 4, 18}; begin at decimal address 1000; assume each int occupies 4 bytes and each pointer occupies 8 bytes. The Coding & DSA category connects this memory model to related programming foundations.
An array object and a pointer object are different things
Start with int a[5] = {12, 7, 25, 4, 18}; int *p = a;. Here, a is one array object containing five contiguous int elements. It occupies 5 * 4 = 20 bytes under our assumptions. The separately declared object p is a pointer that stores the address of a[0]; it occupies 8 bytes in this illustration.
Expression | Type or conversion | Meaning |
|---|---|---|
| Converts to | Points at |
|
| Address of the first element |
|
| A modifiable pointer object |
|
| Pointer to the complete five-element array |
All four can print 1000 at the start. Equal displayed addresses do not imply equal types, object sizes or pointer-arithmetic steps. This conversion of an array expression is called array-to-pointer conversion, commonly called decay. An array is not a pointer. For declarations, two-dimensional arrays and exam patterns, use Arrays and Pointers in C: Complete Guide with Worked Examples for GATE and Interviews. With a, one object and one base address are enough to calculate every step from decay to the one-past pointer.
Array decay happens in expressions, but not everywhere
The assignment p = a works because a decays to a pointer to its first element. Indexing uses the same rule: a[i] means *(a + i). Therefore, a[2] and *(a + 2) both read the value 25.
Two important contexts preserve the array. In the block where a is defined, sizeof a measures the complete array. The expression &a takes the address of that complete array, so its pointed-to type is int[5].
The pointer variable is modifiable, so p++ is valid when the resulting pointer stays within the array or reaches its one-past position. In contrast, a++ and a = p are invalid. The array name is not a modifiable pointer variable. Calling it a constant address hides this crucial type distinction.
Worked memory trace: values, addresses and pointer movement
The trace starts as follows:
| 0 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|---|
| 12 | 7 | 25 | 4 | 18 |
| 1000 | 1004 | 1008 | 1012 | 1016 |
| 1000 | 1004 | 1008 | 1012 | 1016 |
Each int step adds 4 bytes. Thus, a + 2 points at 1000 + 2 * 4 = 1008, and *(a + 2) reads 25. Similarly, p[3] is *(p + 3): the address is 1000 + 3 * 4 = 1012, where the value is 4.
Now execute *(p + 1) = 30. The target address is 1000 + 1 * 4 = 1004, so the shared array becomes {12, 30, 25, 4, 18}. Next, p = p + 4 makes p hold 1000 + 4 * 4 = 1016, and *p is 18. Moving p changes only the pointer variable. It does not move the array or change the base represented by a.
![Memory strip of int a[5] starting at address 1000 in 4-byte cells, with a[1] changed to 30 and pointer p moving from 1000 to 1016.](https://cdn.knowledgegate.ai/blog-assets/blog_asset_1784220186938_z9ln9k.jpg)
Why a + 1 and &a + 1 land at different addresses
After decay, a + 1 advances by one int, so it points at 1000 + 4 = 1004. The expression &a + 1 advances by one complete int[5], so it points one past the 20-byte array at 1000 + 20 = 1020. A one-past pointer may be formed, but it must not be dereferenced.
The related size calculations in the defining block are:
sizeof a = 5 * 4 = 20sizeof a[0] = 4sizeof a / sizeof a[0] = 20 / 4 = 5sizeof p = 8, only under this illustration's pointer-size assumption
![Two number lines from address 1000: a+1 advances 4 bytes to 1004, while &a+1 advances 20 bytes to 1020 past the whole int[5] array.](https://cdn.knowledgegate.ai/blog-assets/blog_asset_1784220187638_h1ye8n.jpg)
Passing an array to a function passes a pointer view
Consider int sum(const int x[], size_t n). In a function parameter, const int x[] is adjusted to const int *x. The brackets neither copy five elements nor carry the length. Inside sum, sizeof x is 8 under our assumption, not 20, so the function needs a separate n.
Call sum(a, 5) after the mutation. The loop reads {12, 30, 25, 4, 18}, producing running totals 12, 12 + 30 = 42, 42 + 25 = 67, 67 + 4 = 71, and 71 + 18 = 89. Its valid traversal range is [x, x + n). The one-past pointer x + 5 may be formed for a loop condition, but not dereferenced.
Traps: declarations, bounds and writable storage
Looks similar | What it really means | Safe correction |
|---|---|---|
| Array of three | Parse outward from |
| One pointer to an array of three | Use parentheses deliberately around |
Bounds matter too. a + 5 forms the valid one-past pointer, while *(a + 5) has undefined behaviour. Pointer subtraction and ordering are meaningful only within the same array object, including its one-past position. Comparing unrelated objects this way is not portable.
Storage also changes what can be written. char s[] = "GATE"; creates a writable array copy, so s[0] = 'g' is valid. char *t = "GATE"; points at a string literal, and attempting t[0] = 'g' has undefined behaviour. Arrays and Strings in C: Array-to-Pointer Decay, sizeof Traps and 2D Address Arithmetic extends the same rules to string terminators, sizeof comparisons and row-major two-dimensional addresses. The five-element array a isolates the earlier step: how decay and pointed-to type determine each address increment.
How questions turn the relationship into output and type traps
Stable question patterns ask you to translate indexing into pointer arithmetic, predict sizeof in a caller and a function parameter, distinguish int *q[3] from int (*r)[3], or identify a one-past dereference and a string-literal write as undefined behaviour.
Use the locked trace for three rapid checks:
*(a + 3)is 4 at address1000 + 3 * 4 = 1012.&a + 1represents address1000 + 5 * 4 = 1020.After the mutation,
sizeof a / sizeof a[0]remains20 / 4 = 5. Values do not affect the array's type or extent.
Short version and the next practice step
Keep five truths together:
An array is storage for a fixed number of contiguous elements.
It decays to a pointer to its first element in most expressions.
sizeof aand&apreserve the complete array type.Pointer arithmetic scales by the pointed-to type.
Bounds still matter even when an address can be computed.
Redraw the 1000-to-1020 memory strip from memory, recompute the three rapid checks, and write sum with a pointer plus an explicit length. The C Language Course: Concepts, MCQs & Coding provides structured concept and practice coverage.




