After the pointer manipulations are done, the layout in memory is represented by the diagrams. (The addresses are arbitrary, but relative)
Given the declarations:
char *strings[] = {"First", "Second", "Third", "Fourth"};
char **ppstr = strings;
the output is as follows:
printf("%c\n", **ppstr); /* a character, 'F' */
printf("%s\n", *ppstr); /* a string, "First" */
printf("%c\n", *ppstr[0]); /* a character, 'F' */
printf("%s\n", &**ppstr); /* a string, "First" */
++*ppstr; /* indirect, inc contents (pointer) */
printf("%c\n", **ppstr); /* a character, 'i' */
printf("%s\n", *ppstr); /* a string, "irst" */
(*++ppstr)++; /* inc ppstr (pointer), indirect, inc contents (pointer) */
(*ppstr)++; /* indirect, inc contents (pointer) */
printf("%c\n", **ppstr); /* a character, 'c' */
printf("%s\n", *ppstr); /* a string, "cond" */
ppstr += 2; /* inc ppstr (pointer to pointer) by 2 (8) */
*ppstr += 4; /* inc contents of ppstr (pointer to char) by 4 */
printf("%c\n", **ppstr); /* a character, 't' */
printf("%s\n", *ppstr); /* a string, "th" */
Complete code for the above examples.