When you add 1 to an int pointer, the address doesn’t move by 1 byte — it moves by one whole int. That scaling rule is the heart of pointer arithmetic in C, and it’s what this question from our C Programming Quiz App checks. If you can explain why *(p + 1) prints the second array element, you understand how arrays and pointers cooperate in C.
The Quiz Question
int arr[] = {1, 2, 3};
int *p = arr;
printf("%d", *(p + 1));
What is printed by this code?
- 1
- 2
- 3
- An address
The Correct Answer: 2
In the initializer int *p = arr, the array name decays to a pointer to its first element — p now points at arr[0]. Adding 1 to an int * advances it by one int, so p + 1 points at arr[1], and dereferencing gives 2. Verified on gcc 13.3 and Apple clang 21:
$ gcc -Wall -Wextra arith.c && ./a.out 2
You can watch the scaling happen by printing the raw addresses:
printf("%p %p", (void *)p, (void *)(p + 1));
0x7ffc25d1919c 0x7ffc25d191a0 ← 4 bytes apart, one sizeof(int)
The two addresses differ by 4 — sizeof(int) on this platform — even though we only added 1. The compiler multiplies the offset by the size of the pointed-to type. That’s why the same + 1 would move a double * by 8 bytes and a char * by exactly 1.
Why Each Wrong Answer Is Wrong
Why not 1?
1 is *p — the element p points at before any arithmetic. Answering 1 means ignoring the + 1, or assuming a pointer somehow “stays” at the start until moved with p++. But p + 1 is an ordinary expression: it computes a new address without modifying p.
Why not 3?
3 lives at *(p + 2). This answer usually comes from off-by-one thinking — “the 1st offset is the 1st element”. Offsets in C start at 0: p + 0 is arr[0], p + 1 is arr[1].
Why not “An address”?
p + 1 alone is an address — but the expression we print is *(p + 1), and the star dereferences that address back to an int. Printing the address itself would need printf("%p", (void *)(p + 1)). If you passed a pointer to %d, both gcc and clang would warn about a format mismatch under -Wall.
*(p + i) Is Exactly a[i]
The C standard defines the subscript operator in terms of pointer arithmetic: E1[E2] means *((E1) + (E2)). So all four of these read the same element:
arr[1] /* the familiar spelling */
*(arr + 1) /* what the compiler sees */
p[1] /* subscripting a pointer */
*(p + 1) /* our quiz expression */
This identity is why pointers can walk arrays so naturally — and it’s also behind the party trick that 2[a] compiles and runs. One boundary to respect: pointer arithmetic is only defined while the result stays inside the array (or one element past its end, for comparisons). p + 3 here may be formed but not dereferenced; p + 4 is undefined even to compute.
Frequently Asked Questions
Does p + 1 add one byte to the address?
Only for char *. For any other type, p + 1 advances by sizeof(*p) bytes — 4 for int on typical platforms, 8 for double. Pointer arithmetic always counts in elements, not bytes.
Is *(p + 1) the same as p[1]?
Yes, by definition. The standard specifies p[1] as *((p) + (1)). They compile to identical code; pick whichever reads better.
Does p + 1 change the pointer p?
No. p + 1 computes a new address and leaves p untouched, just as x + 1 doesn’t change x. To move the pointer itself you need an assignment: p = p + 1 or p++.
Related Reading
- Pointers in C – Complete Guide
- Array Summation Using Pointers
- C Program to Insert an Element into an Array
- C Aptitude: Endianness and Pointer Arithmetic
Recommended Books
- The C Programming Language – Kernighan & Ritchie (India) | Amazon.com
- C Programming: A Modern Approach – K.N. King (India) | Amazon.com
This question is #15 in the C Programming Quiz App — 155 questions with explanations covering operators, pointers, memory, and more.
Download on Google Play →