[C言語] Cパズルブック 2.1.1 文字型, 文字列型, 整数型

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

難しかった第6章が終わり、前に戻って第2章から始めます。

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

整数5は文字列としてはASCIIコード35(16進数, 10進数では53)になります。

LLDBデバッガで確認したところ、最初の2変数はスタック領域に整数やASCIIコードとして格納されていますが、stringはポインタなのでメモリアドレスが格納されていました。文字列”5″はスタック領域の前の方に格納されていました。

#include "stdio.h"
#define PRINT(format, x) printf("x = %"#format"\n",x)

int integer = 5;
char character = '5';
char *string = "5";

int main() {
        PRINT(d, string);
        PRINT(x, string); // 追加
        PRINT(x, &string); // 追加
        printf("\n");

        PRINT(d, character);
        PRINT(d, integer);
        PRINT(s, string);
        PRINT(c, character);
        PRINT(c, integer=53);
        PRINT(d, ('5' > 5));

    return 0;
}
x = 10420060
x = 9eff5c
x = 9f4008

x = 53
x = 5
x = 5
x = 5
x = 5
x = 1 // 53(10進数) > 5はTRUE

[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