The only way to really understand this kind of stuff (memory management, pointer behaviour, etc.) is to experiment yourself. Anyway, I smell someone is trying to seem clever fooling students, so I will try to clarify a few things.
int a[NUM]={20,-90,450,-37,87};
int *p;
This structure in memory would be something like:

This creates a vector of five int
, so far, so good. The obvious move, given that data, is to run over the elements of a using p
. You would do the following:
for(p = a; p < (a + NUM); ++p) {
printf("%d ", *p);
}
However, the first change to notice is that both loops convert the pointers to char
. So, they would be:
for (p=a;(char *)p<((char *)a+sizeof(int)*NUM); ++p) {
printf("%d ", *p);
}
Instead of pointing to a
with a pointer to int
the code converts p
to a pointer to char
. Say your machine is a 32bit one. Then an int
will probably occupy four bytes. With p
being a pointer to int
, when you do ++p
then you effectively go to the next element in a
, since transparently your compiler will jump four bytes. If you convert the int
pointer to a char
instead, then you cannot add NUM
and assume that you are the end of the array anymore: a char
is stored in one byte, so ((char *)p) + 5
will point to the second byte in the second element of a
, provided it was pointing at the beginning of a
before. That is way you have to call sizeof(int)
and multiply it by NUM
, in order to get the end of the array.
And finally, the infamous *p++ = ++*p<60 ? *p : 0;
. This is something unfair to face students with, since as others have already pointed out, the behaviour of that code is undefined. Lets go expression by expression.
++*p
means "access p
and add 1 to the result. If p
is pointing to the first position of a
, then the result would be 21. ++*p
not only returns 21, but also stored 21 in memory in the place where you had 20. If you were only to return 21, you would write; *p + 1
.
++*p<60 ? *p : 0
means "if the result of permanently adding 1 to the value pointed by p
is less than 60
, then return that result, otherwise return 0.
*p++ = x
means "store the value of x
in the memory address pointed by p
, and then increment p
. That's why you don't find ++p
or p++
in the increment part of the for
loop.
Now about the whole instruction (*p++ = ++*p<60 ? *p : 0;
), it is undefined behaviour (check @Lundin's answer for more details). In summary, the most obvious problem is that you don't know which part (the left or the right one), around the assignment operator, is going to be evaluated first. You don't even know how the subexpressions in the expression at the right of the assignment operator are going to be evaluated (which order).
How could you fix this? It would be actually be very simple:
for (p=a;(char *)p<((char *)a+sizeof(int)*NUM); ++p) {
*p = (*p + 1) <60 ? (*p + 1) : 0;
}
And much more readable. Even better:
for (p = a; p < (a + NUM); ++p) {
*p = (*p + 1) <60 ? (*p + 1) : 0;
}
Hope this helps.