GATE 2015 COMPUTER SCIENCE & INFORMATION TECH. – CS – C Programming | Q. 62 (Shift – 1)
x
is 2000 (in decimal) and an integer requires four bytes of memory.
int main() { unsigned int x[4][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12} }; printf("%u, %u, %u", x+3, *(x+3), *(x+2)+3); }
Solution
| Index | Column 0 | Column 1 | Column 2 |
|---|---|---|---|
| Row 0 | x[0][0] = 1 | x[0][1] = 2 | x[0][2] = 3 |
| Row 1 | x[1][0] = 4 | x[1][1] = 5 | x[1][2] = 6 |
| Row 2 | x[2][0] = 7 | x[2][1] = 8 | x[2][2] = 9 |
| Row 3 | x[3][0] = 10 | x[3][1] = 11 | x[3][2] = 12 |
Before solving the 2-D array question, let us first understand the relationship between an array and a pointer using a simple 1-D array.
This array contains 3 elements. Remember that array indexing starts from 0.
| Index | Element | Value | Pointer Expression |
|---|---|---|---|
| 0 | a[0] | 10 | a or (a + 0) = &a[0] |
| 1 | a[1] | 20 | (a + 1) = &a[1] |
| 2 | a[2] | 30 | (a + 2) = &a[2] |
Therefore:
a + 1 → points to a[1] → value 20
a + 2 → points to a[2] → value 30
To obtain the value stored at these locations, we use the dereference operator (*):
*(a + 1) = a[1] = 20
*(a + 2) = a[2] = 30
Now let us apply the same idea to the 2-D array used in this question:
This array has 4 rows and 3 columns. In a 2-D array, the array name x, when used in an expression, represents a pointer to the first row.
| Row | Array Row | Pointer Expression | Points To |
|---|---|---|---|
| Row 0 | x[0] | x or x + 0 | Row 0 |
| Row 1 | x[1] | x + 1 | Row 1 |
| Row 2 | x[2] | x + 2 | Row 2 |
| Row 3 | x[3] | x + 3 | Row 3 |
x[1] = {4, 5, 6}
x[2] = {7, 8, 9}
x[3] = {10, 11, 12}
x → points to Row 0
x + 1 → points to Row 1
x + 2 → points to Row 2
x + 3 → points to Row 3
The question states that the address of x is 2000 (in decimal), and each unsigned int requires 4 bytes of memory.
| Element Address | Address (Decimal) |
|---|---|
| &x[0][0] | 2000 |
| &x[0][1] | 2004 |
| &x[0][2] | 2008 |
| &x[1][0] | 2012 |
| &x[1][1] | 2016 |
| &x[1][2] | 2020 |
| &x[2][0] | 2024 |
| &x[2][1] | 2028 |
| &x[2][2] | 2032 |
| &x[3][0] | 2036 |
| &x[3][1] | 2040 |
| &x[3][2] | 2044 |
2000 → 2004 → 2008 → 2012 → 2016 → … → 2044
Each successive unsigned int occupies the next 4 bytes of memory.
We have already seen that x is a 2-D array with 4 rows and 3 columns. In a 2-D array, pointer arithmetic with the array name x moves row by row.
x + 1 → Row 1
x + 2 → Row 2
x + 3 → Row 3
x + 3 points to Row 3 of the 2-D array.
Row 3 contains three elements:
| Element | Value | Address |
|---|---|---|
| x[3][0] | 10 | 2036 |
| x[3][1] | 11 | 2040 |
| x[3][2] | 12 | 2044 |
Since x + 3 points to the beginning of Row 3, it points to the address where Row 3 starts.
&x[3] = &x[3][0]
&x[3][0] = 2036
Although Row 3 contains three elements at addresses 2036, 2040, and 2044, the expression x + 3 points to the start of Row 3. Therefore, its address is 2036.
x + 3 = 2036
We have already established that x + 3 points to Row 3 of the 2-D array.
x + 3 = &x[3]
&x[3] = &x[3][0] = 2036
Row 3 contains three elements:
| Element | Value | Address |
|---|---|---|
| x[3][0] | 10 | 2036 |
| x[3][1] | 11 | 2040 |
| x[3][2] | 12 | 2044 |
x[3] represents the entire fourth row: {10, 11, 12}.
But there is one more important point. Since x[3] is an array, when it is used in an expression, it is converted to a pointer to its first element.
↓
&x[3][0]
↓
Address = 2036
*(x + 3) = x[3]
x[3] is the fourth row {10, 11, 12}. When this array is used as a value in an expression, it refers to the address of its first element, x[3][0].
Therefore: *(x + 3) = 2036
x + 3 → Row 3 → *(x + 3) → x[3] → &x[3][0] → 2036
The expression we are evaluating in the question is:
We already know that:
*(x + 3) → gives Row 3
Row 3 is:
The array x[3] can be converted to a pointer to its first element when it is used in a context where a pointer is required. In that case:
x[3] → &x[3][0]
&x[3][0] = 2036
We should not immediately say that *(x + 3) is 2036. The exact type and context of the expression must be considered.
Let us evaluate the expression step by step:
In the 2-D array, x points to Row 0. Therefore:
x + 2 → Row 2
Row 2 contains: {7, 8, 9}
*(x + 2) = x[2]
Therefore, *(x + 2) represents Row 2:
x[2] = {7, 8, 9}
Here we have:
x[2] + 3
Since x[2] is an array, in this expression it is converted to a pointer to its first element:
x[2] → &x[2][0]
| Element | Value | Address |
|---|---|---|
| x[2][0] | 7 | 2024 |
| x[2][1] | 8 | 2028 |
| x[2][2] | 9 | 2032 |
The pointer starts at &x[2][0], whose address is 2024.
Each unsigned int occupies 4 bytes. Therefore, moving 3 positions means:
3 × 4 = 12 bytes
Hence:
2024 + 12 = 2036
*(x + 2) + 3
= x[2] + 3
= &x[2][0] + 3
= 2024 + (3 × 4)
= 2036
From the above calculations:
*(x + 2) + 3 = 2036
Therefore, the required output of the given printf() expression is:
(A) 2036, 2036, 2036

