Reputation: 81
int stud[5][2] = {{1,2},{3,4},{5,6},{7,8},{9,8}};
printf("%u %u",*(stud+1),stud+1);
printf("%u, %u", &stud,stud);
Why this statement prints similar values, stud[1] or *(stud+1) is actually an array hence must get the base address i.e &stud[0][0], but stud itself is a pointer to an array of array. Also the third statement prints identical values.
Upvotes: 1
Views: 87
Reputation: 9680
int stud[5][2] = {{1,2},{3,4},{5,6},{7,8},{9,8}};
The above statement defined stud
to be an array of 5
elements where each element is of type int[2]
, i.e., an array of 2
integers. It also initializes the array with an initializer list.
Now, in the expression stud + 1
, the array stud
decays into a pointer to its first element. Therefore, stud + 1
evaluates to &stud[1]
and is of type int (*)[2]
, i.e., a pointer to an array of 2
integers . *(stud + 1)
is then *(&stud[1])
, i.e., stud[1]
. stud[1]
is again an array type, i.e., int[2]
, so it again decays to a pointer to its first element, i.e., &stud[1][0]
(which is the base address of second element of the array stud[1]
) in the printf
call.
Please note that stud + 1
and *(stud + 1)
evaluate to the same address but they are not the same type.
Similarly, &stud
and stud
decay to the same address but they are different types. stud
is of type int[5][2]
where as &stud
is of type int (*)[5][2]
.
Why this statement prints similar values, stud[1] or *(stud+1) is actually an array hence must get the base address i.e &stud[0][0], but stud itself is a pointer to an array of array.
You are wrong here. The base address of stud[1]
or *(stud + 1)
is &stud[1][0]
and not &stud[0][0]
. Also, stud
is not a pointer but an array type. It decays to a pointer to its first element in some cases like here but it does mean it is a pointer.
Also, you should use %p
conversion specifier for printing addresses.
Upvotes: 2
Reputation: 66194
Your observations are correct concerning the expressions are all address-results. But the types of those addresses per the standard are different. Your phrase "but stud itself is a pointer to an array of array". is not accurate. stud
is an array of arrays. Pointers are not arrays. After decades of trying to come up with a solid vernacular that describes how it works, and refusing steadfastly to walk the "decay" plank (a word that appears exactly one times in the C standard and even there it is used as a verb-footnote), the best I could come up with is this:
Pointers are not arrays. A pointer holds an address. An array is an address.
Each expression is shown below Given int stud[5][2];
stud int (*)[2]
stud+1 int (*)[2]
*(stud+1) int *
&stud int (*)[5][2]
Remembering that, per the standard, the expressive value of an array is the address of its first element, and pointer-to-element-type is the type of said-address. In both outputs each pair of expressions have equivalent addresses, but they're different types. This is verifiable with some expansion of the original code:
#include <stdio.h>
int main()
{
int stud[5][2] = {{1,2},{3,4},{5,6},{7,8},{9,8}};
printf("%p %p\n", *(stud+1), stud+1);
printf("%p %p\n", &stud,stud);
int (*p1)[2] = stud+1; // OK
// int (*p2)[2] = *(stud+1); // incompatible types
int *p3 = *(stud+1); // OK
int (*p4)[5][2] = &stud; // OK
return 0;
}
Upvotes: 2
Reputation: 4868
Lets analyze the program
int stud[5][2] = {{1,2},{3,4},{5,6},{7,8},{9,8}};
Now address will be like this (assuming 2 byte integer). Brackets denote corresponding elements in array.
1 element of 2-D array ---> 4001(1) 4003(2)
2 element of 2-D array ---> 4005(3) 4007(4)
3 element of 2-D array ---> 4009(5) 4011(6)
4 element of 2-D array ---> 4013(7) 4015(8)
5 element of 2-D array ---> 4017(9) 4019(8)
We know that arr[i] gives the ith element of array. So when we say stud[0] we expect 0th element of array stud[5][2]
.
We can assume 2-d array as collection of 1-d array. So with statement like printf("%u",stud[0])
we exptect 0th element to get printed and what is 0th element for this array. It is one dimensional array. We know that just mentioning 1-D array gives its base address. Hence printf
would print base address of 0th 1-D array and so on.
With this information we can analyze your problem.
Remember stud is 2-D array. stud
is treated as pointer to zeroth element of 2-D array. So (stud + 1)
would give address of 2nd element of 2-D array. And thus printing (stud+1)
would print address of 2nd element of stud array. What is it. It will be 4005 from above addresses.
Now lets see why *(stud +1) also gives the same value.
Now we know that *(stud +1)
is equivalent to stud[1]
. From above we know stud[1] would print base address of 2nd 1-D array. What is 1-d array at 2nd position it is (3,4) with address (4005,4007). So what is it base address. It is 4005. Thus *(stud+1)
also prints 4005.
Now you say stud[0] and &stud[0]
print the same value.
From above stud[0] is 1-d array and printing it gives its base address. Now so &stud[0] should give address of 1-D array which is same as its base address. Thus they print the same address.
Similar explanation will hold for other cases.
Upvotes: 0
Reputation: 272
Since all of those values you are trying to display are all pointers you should use %p
instead of %u
. If you do that you will see that the addresses pointed to:
printf("%p, %p", &stud,stud);
are different than:
printf("%p %p",*(stud+1),stud+1);
because as you said stud
is a pointer to an array of array.
Upvotes: 0
Reputation: 141534
Without using any decaying syntax it may be clearer (these are the same addresses as your code; the first line is in the opposite order; and my parentheses are redundant but hopefully it improves clarity of this example):
printf( "%p %p\n", &(stud[1]), &(stud[1][0]) );
printf( "%p %p\n", &(stud), &(stud[0]) );
In both cases the first address on the line matches the second because the first element of an array lives at the same address as the array. Arrays can't have initial padding, and in C the address of an object is the address of its first byte.
The first element of stud
is stud[0]
, and the first element of stud[1]
is stud[1][0]
.
Upvotes: 1