Pointer Stew

This is a puzzle that uses pointers and arrays in a complex manner. If you completely understand how this works, you definitely know your C pointers and arrays.

The Program

Line numbers are included for reference; they don’t appear in the source code, of course.

1. #include <stdio.h>
2. char *c[] = {
3.     "ENTER",
4.     "NEW",
5.     "POINT",
6.     "FIRST"
7. };
8. char **cp[] = { c+3, c+2, c+1, c };
9. char ***cpp = cp;
10. int main(void)
11. {
12.     printf("%s", **++cpp );
13.     printf("%s ", *--*++cpp+3 );
14.     printf("%s", *cpp[-2]+3 );
15.     printf("%s\n", cpp[-1][-1]+1 );
16.     return(0);
17. }

Analysis

Line 12: **++cpp

Here, cpp points to cp. As cp is an array of pointers to pointers to characters, the “++” changes cpp to point to cp + 1. Then the first dereference (“*”) is to c + 2, and the second dereference (“*”) is to *(c + 2), or c[2], or the string “POINT”.

So the printf on line 12 prints the string POINT with no trailing newline.

After this, cpp points to cp + 1. The other variables are unchanged.

Line 13: *--*++cpp+3

First, we apply the rules of precedence to parenthesize this expression. This produces “(*(--(*(++cpp))))+3s”. Now, cpp points to cp + 1. After applying the “++” operator, cpp points to cp + 2. Then the first dereference (“*”) is to c + 1, and applying the decrement operator “-{-}” changes the entry in the location cp + 2 to be c + 1 - 1, or c. The second dereference (“*”) thus is *c, or c[0], or the string “ENTER”. Adding 3 to this value takes us to c[0] + 3, which is the string “ER”.

So the printf on line 13 prints the string ER with a trailing blank and no trailing newline.

After this, cpp points to cp + 2 and cp[2] points to c. The other variables are unchanged.

Line 14: *cpp[-2]+3

Again, we fully parenthesize this to get (*(cpp[-2]))+3.

As cpp points to cp + 2, the dereference “cpp[-2]” is to *(cp + 2 - 2) or *cp, or c + 3. Then the dereference “*” takes us to *(c + 3), or c[3], or the string “FIRST”. Adding 3 to this takes us to c[3] + 3, or which is the string “ST”.

So the printf on line 14 prints the string ST with no trailing newline.

Line 15: cpp[-1][-1]+1

As cpp still points to cp + 2, the dereference “cpp[-1]” is to *(cp + 2 - 1) or *(cp+1), or c + 2. Then the next “[-1]” takes us to *(c + 2 - 1), or *(c + 1), or c[1], or the string “NEW”. Adding 1 to this takes us to c[1] + 1, or which is the string “EW”.

So the printf on line 15 prints the string EW with a trailing newline.

Result

So the result of this program is the line


POINTER STEW

Credit

This problem is from Alan Feuer’s excellent book The C Puzzle Book (Addison-Wesley Professional, Boston, MA; ©1998; ISBN 978-0-201-60461-0). This document has a slightly modified version by Matt Bishop. Only changes necessary to get it to compile without warnings were made. The C code analyzed above is as in the original.


UC Davis sigil
Matt Bishop
Office: 2209 Watershed Sciences
Phone: +1 (530) 752-8060
Email: mabishop@ucdavis.edu
ECS 36A, Programming and Problem Solving
Version of September 20, 2019 at 8:37PM

You can also obtain a PDF version of this.

Valid HTML 4.01 Transitional Built with BBEdit Built on a Macintosh