When you add an integer (say, 4) to a pointer, C will not just add 4 bytes to your pointer. Rather, it scales the integer to the size of the pointed-to object, so if you added 4 to a pointer to int, you get the fourth int, not the fourth byte.
This is why the code is casting &a[0] (a pointer) to an int: now when an integer is added, scaling is not done. But casting a pointer to an int is really not a good idea. To achieve what this code is trying to do, you want to cast to a pointer to char. A char is a byte, so no scaling is needed, and the conversion to a char pointer is much less dicey than the conversion to an int. So, with that modification, here's what's going on:
Code:
int a[10] = { 0, 1, 2 };
int k = 2;
/* Now I'll break it down into some rather useless
* C statements for illustrative purposes.
*/
/* This is a pointer to the first element of your array.
* The pointer has type int *.
*/
&a[0];
/* This expression is also a pointer to the first element,
* but more properly, to the first byte of the first element.
* It has type char *.
*/
(char *)&a[0];
/* Now k * sizeof(int) bytes are being added to the char
* pointer. The resulting value is a pointer to the "k"th
* element of the array (since k is 2, this is the 2nd element).
*/
(char *)&a[0] + k * sizeof(int);
/* Great, we have a pointer to the 2nd element. But our
* pointer has type char *, which means if we try to
* dereference it, we'll only get a single byte. So, convert
* the pointer to an int *, so a dereference will get the
* whole int.
*/
(int *)((char *)&a[0] + k * sizeof(int));
/* And finally, the dereference. */
*(int *)((char *)&a[0] + k * sizeof(int));
printf("%d\n", *(int *)((char *)&a[0] + k * sizeof(int)));
Pointing a char * at any object (like I've done above) is legal, at least in C99. Converting it back to an int * I'm not so sure about, but an implementation would probably have to go to some extra effort to prevent you from doing it. It's not too useful, of course, since we have the [] operator for array access.