As far as the pointer assignment:
To take a comment from below:
"the memory layout of an array of ints and an array of struct composed
solely by ints is the same"
The reason pointer types must be defined are because the compiler must know the size of the data the pointer is pointing to. Integers have a size of 4 byes, while this struct would have a size of 8 bytes. When the program tries to access the memory at location s[1], the compiler knows that the program wants the data 8 bytes after s[0], where i[1] would want the data only 4 bytes after i[0].
s is an array of structs(with two members of type int), i is a pointer to an int. Since the first element of s is a struct of 2 ints, i = s assigns the address of the first member of the first element of s to i.
i = &s[0] is the same assignment.
If s[0] started at 0x00, it's first member has the address 0x00, while it's second member has the address 0x04. s[1] would start at 0x08, the struct at that location has a second member with the address 0x0C.
With i = s, i[0] has the address 0x00, while i[1] has the address 0x04, the second member of the first element of s. i[2] has the address 0x08, the first member of the second struct in the array, i[3] has the address 0x0C, the second member of the second struct in the array. And so on...
{ 10, 20 } { 15, 25 } { 8, 75 } { 6, 2 }
s:| 0 | 1 | 2 | 3 |
i:| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
i now points at the first integer (out of all 8).
i[0] = 10
i[7] = 2
The first printf statement is interpreted as follows: Since i[7] = 2, then we have s[2] referring to the pair {8,75}, that has the x value 8.
The pointers indeed are incompatible, compiling with gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5.1) produces the following warning:
test.c: In function ‘main’: test.c:10: warning: assignment from
incompatible pointer type
However, the program does compile and product the output:
8 75 15 20 85