Pointer Stew, Revisited

Here’s my take on Pointer Stew, for those who are curious.


char *c[]={
        "ENTER",
        "NEW",
        "POINT",
        "FIRST"
};

char **cp[]={c+3,c+2,c+1,c};
/*
cp[0] == &c[3] == &"FIRST"
cp[1] == &c[2] == &"POINT"
cp[2] == &c[1] == &"NEW"
cp[3] == &c[0] == &"ENTER"
*/

char ***cpp=cp;
/*
cpp[0] == cp[0] == &c[3] == &"FIRST"
cpp[1] == cp[1] == &c[2] == &"POINT"
cpp[2] == cp[2] == &c[1] == &"NEW"
cpp[3] == cp[3] == &c[0] == &"ENTER"
*/

main()
{
        printf("%s",**++cpp);
/*
RULE: prefix unary operators are all the same precedence and associate right->left
RULE: prefix unary increment returns incremented value to the expression

1)  **++cpp ---> *(*(++cpp))
 - increment cpp.  the new table looks like:
cpp[0] == cp[1] == &c[2] == &"POINT"
cpp[1] == cp[2] == &c[1] == &"NEW"
cpp[2] == cp[3] == &c[0] == &"ENTER"

2)  *(*cpp)
 - dereference cpp: *cpp == cpp[0] == cp[1] == &c[2] == &"POINT"

3) *(&"POINT")
 - dereference a reference, leading to: "POINT"

4) printf("%s", "POINT")
 - output "POINT"
*/

        printf("%s ",*--*++cpp+3);
/*
RULE: prefix unary operators are all the same precedence and associate right->left
RULE: binary addition/subtraction operators bind below prefix unary operators
RULE: binary addition/subtraction on pointer types adds/subtracts the size of the object pointed to

1) (*(--(*(++cpp)))) + 3
 - increment cpp.  the new table looks like:
cpp[0] == cp[2] == &c[1] == &"NEW"
cpp[1] == cp[3] == &c[0] == &"ENTER"

2) (*(--(*cpp))) + 3
 - dereference cpp: *cpp == cpp[0] == cp[2] == &c[1] = &"NEW"

3) (*(--&"NEW")) + 3
 - unary prefix decrement &"NEW", which is sizeof(char*), yielding &"ENTER"
   (ref. c[])
 
4) (*(&"ENTER") + 3
 - dereference a reference --> "ENTER"

5) "ENTER" + 3
 - add 3 to the char* --> "ER"

6) printf("%s ", "ER")
 - output "ER "

*/
        printf("%s",*cpp[-2]+3);
/*
RULE: postfix unary operators ([] in this case) bind tightest of the operators here
RULE: prefix arethmetic operations do the obvious thing
RULE: prefix unary operators bind next 
RULE: binary plus/minus are last of the ones here

1) (*(cpp[-2]) + 3
 - we've bumpted cpp twice so far, so we can safely decrement it back to where it started
 - cpp[-2] == cp[0] == &c[3] == &"FIRST"

2) (*(&"FIRST") + 3
 - dereference reference: --> "FIRST"

3) "FIRST" + 3 --> "ST"

4) printf("%s", "ST")
 - output "ST"

 */

        printf("%s\n",cpp[-1][-1]+1);
/*
RULE: postfix unary operators ([] in this case) bind tightest and associate L->R
RULE: binary plus/minus are least precedent
RULE: array subscripting is done by multiplying the integer by the sizeof the
      array element and adding it to the pointer, followed by applying the
      dereference operator, unless the result is itself an array

1) ((cpp[-1])[-1]) + 1
 - again, we can decrement cpp by one due to previous two increments
 - cpp[-1] == cp[1] == &c[2] == &"POINT"

2) (&"POINT"[-1]) + 1
 - subject to rule #3, we have &"POINT" - sizeof(char*) --> *(&"NEW") (cf c[])

3) (*(&"NEW")) + 1
 - dereference the reference --> "NEW"

4) "NEW" + 1
 - pointier math: add sizeof(char) --> "EW"

5) printf("%s\n", "EW");
 - output: "EW\n"

final output:  "POINT" "ER " "ST" "EW\n" --> "POINTER STEW\n"

NOTE that this clever little thing managed to get the 0-terms right every time;
otherwise, the printf's would have crashed
 */
}

One Reply to “Pointer Stew, Revisited”

Leave a Reply

Your email address will not be published. Required fields are marked *