[C言語] Cパズルブック 6.4 ポインタによる混乱

『Cパズルブック』(Alan R.Feuer, 1985)
[Mac M2 Pro 12CPU, macOS Ventura 13.3.1, clang 14.0.3]

問6.4のコードと出力は以下の通りです。

インクリメント++やデクリメント–では配列の基準点が移動しますが、添字では移動せず読み取りだけであるというところがポイントです。教本P151以降に詳しい解説があります。

ポインタの特徴を生かしつつ極力ややこしくした問題です。アスタリスクを3つも並べるに至っては狂気の沙汰です。このような問題でポインタ嫌いになりC言語から離れていった方が量産されたのではないでしょうか。

ただ当時のメモリやストレージの貧弱さを考えるとこのような手法はおふざけではなく真面目に使われることもあったのでしょう。

#include "defs.h"

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

char **cp[] = {c+3, c+2, c+1, c};
char ***cpp = cp;

int main() {
        printf("%s\n", **++cpp);
        // *(*(++CPP))
        // 1.++CPP
        // cppで配列cpの2番要素c+2へ移る
        // 2.*(++CPP)
        // 配列cのc+2へ移る
        // 3.*(*(++CPP))
        // 参照先の格納文字列"POINT"を指す

        printf("%s\n", *--*++cpp + 3);
        // *(--(*(++cpp)))
        // 1.++cpp
        // cppで3番要素c+1へ移る
        // 2.*(++cpp)
        // 配列cのc+1へ移る
        // 3.--(*(++cpp))
        // 配列cのcへ移る
        // 4.*(--(*(++cpp)))
        // 文字列"ENTER"の先頭へ移る
        // 5.*(--(*(++cpp))) + 3
        // "ENTER"の4番要素以降"ER"を指す

        printf("%s\n", *cpp[-2] + 3);
        // 1.cpp[-2]
        // cppで3番要素から1番要素c+3へフォーカスする。移動はせず基準は3番要素c+1のまま
        // 2.*cpp[-2]
        // 配列cのc+3は"FIRST"
        // 2.*cpp[-2] + 3
        // "FIRST"の4番要素以降"ST"を指す

        printf("%s\n", cpp[-1][-1] + 1);
        // 1.cpp[-1]
        // cppで3番要素c+1から2番要素c+2へフォーカスする。基準は3番要素c+1のまま
        // 2.cpp[-1][-1]
        // 配列cのc+2から1つ左へシフトしてc+1をフォーカスする
        // 3.cpp[-1][-1] + 1
        // c+1である"NEW"の2番要素以降"EW"を指す

    return 0;
}
POINT
ER
ST
EW