A
Anupam
Briggs Reschke <[email protected]> said:The following code fragment is a little puzzle a friend passed on to me (
The origionators name is Christopher Skelly). See If you can determine
its output without compiling it.
------------------------------- cut here --------------------------------
#include <stdio.h>
char *ap[] = {
"INTEGER",
"PROPORTION",
"DEBUGGER",
"PORTABLE",
"TOWER!"
};
char **app[] = {ap + 4, ap + 3, ap + 2, ap + 1, ap};
char ***ppp = app;
char ****pppp = &ppp;
void main()
{
printf("%.*s", 2, *--**pppp);
printf("%.*s", 3, *(++*pppp[0] - 4));
printf("%s ", ++*--*++pppp[0] + 5);
printf("%.*s", 2, *++pppp[0][3] + 3);
printf("%s\n", (*pppp + 2)[-2][2] + 2);
}
---------------------------- end of listing
------------------------------
Now changing that to :
#include <stdio.h>
char *ap[] = {
"INTEGER",
"PROPORTION",
"DEBUGGER",
"PORTABLE",
"TOWER!"
};
char **app[] = {ap + 4, ap + 3, ap + 2, ap + 1, ap};
char ***ppp = app;
char ****pppp = &ppp;
int main(void)
{
printf("%.*s", 2, *--**pppp); /* 1 */
printf("%.*s", 3, *(++*pppp[0] - 4)); /* 2 */
printf("%s ", ++*--*++pppp[0] + 5); /* 3 */
printf("%.*s", 2, *++pppp[0][3] + 3); /* 4 */
printf("%s\n", (*pppp + 2)[-2][2] + 2); /* 5 */
}
The non-ANSI ness seems to be taken care of. Actually solving this
gave me a
good insight into pointers as such so I wanted to share it with every
one.
*Disclaimer : Please note that this is about the worst and most
unreadable
program that may be created ... I just enjoyed the playing around a
bit.*
So here's what I think explains the output .
NOTE 1 : printf("%.2s",whatever); prints only the first two characters
of "whatever".
NOTE 2 : printf("%.*s",2,whatever); picks up the '2' from the 2nd
parameter to itself...
so its just a tangled way of saying the first line ...useful
in other circumstances though.
Take 1.
*pppp is ppp which equals app.
app being applied in an object context is converted to pointer to
app[0].
So **pppp gives app[0]
Now --app[0] deducts 1 from this value leaving the array app[] as :
char **app[] = {ap + 3, ap + 3, ap + 2, ap + 1, ap};
Now *--**pppp equals *(ap+3) which is a pointer to "PORTABLE"
The first two characters are printed out giving "PO".
Take 2.
*pppp[0] is *app.
So ++*pppp[0] does this :
char **app[] = {ap + 4, ap + 3, ap + 2, ap + 1, ap};
The entire expression thus boils down to *(ap + 4 - 4) equalling the
pointer to "INTEGER"
From this the first three letters that is INT is printed out.
Take 3.
++pppp[0] changes the contents of ppp to app+1
--*++pppp[0] thus changes app[1] to ap + 2 giving :
char **app[] = {ap + 4, ap + 2, ap + 2, ap + 1, ap};
++*--*++pppp[0] thus makes the pointer at ap[2] to point to the 'E'
in "DEBUGGER".
++*--*++pppp[0] + 5 yeilds a pointer to the second 'E' in "DEBUGGER".
Thus it prints till the '\0' yielding "ER".
Take 4.
pppp[0] yields app+1.
Thus ++pppp[0][3] is the same as ++app[4] .Thus giving
char **app[] = {ap + 4, ap + 2, ap + 2, ap + 1, ap + 1};
Sp it yields the pointer at ap[1] incremented by 3 ... thus giving
rise to a pointer pointing to
the second 'P' of "PROPORTION".
Now two characters are outputted giving rise to "PO"
Take 5.
It's the same as *(ppp+2-2)[2]+2
That is *(app[1]+2)+2
That is *(ap+4) + 2
That is the pointer to "TOWER" incremented by 2 and now pointing to
'W'.
This is printed out to give "WER".
Thus the output is POINTER POWER.
However it is absolutely dangerous sort of code to experiment with
.. Almost like a grenade without a pin. It looks like that too.
Regards,
Anupam