解答3.1

aは局所変数なので、初期値は全て不定である.

解答3.2

aは大域変数なので、0に初期化される.

解答3.3

sort.c

bsortとswapがソートを行う関数、genがテストデータ生成、 printが出力関数である.
bsortは配列(の先頭要素へのポインタ)とその要素数を 引数とする. 詳しくは4章で学習するが、C言語では 配列全体をそのまま関数の引数や戻り値にすることはできない.

ソートのアルゴリズムは最も単純なバブルソートを使用しているが、 Nが1万でも数秒以内に終了するため実用上問題にならない. 31行目は乱数の系列を変えるおまじないである. これを忘れると関数randの戻り値が毎回同じ順序になるので、 実行結果が変わらない. 戻り値はint型なので、33行目で 値を1-100の範囲にするために剰余を使用している.

解答3.4

引数はchar *a[]であるから文字列の配列である. 文字列の配列は0で終端されている. while文では終端の 検出を行っている. a[i]はi番目の要素であるから、 これは文字列配列の各要素を順に出力する関数であり、 戻り値は配列の要素数である.

解答3.5

int foo(char **a) {
    char **s = a;
    while (*s) {
        printf("%s\n", *s++);
    }
    return (s-a);
}

文字列配列の先頭アドレスは文字列への2重ポインタで表される. 解答3.4ではiを変化させることで要素を走査したが、 解答3.5では別の2重ポインタ変数sを使用する. *sがa[i]に相当するように、whileの本体で sを増加させる必要がある点に注意.
*s++はsを参照した後で値を1単位だけ増加させる. すなわちポインタの大きさ分(4バイトまたは8バイト) がsに加算され、次の要素を指すようになる. 要素の個数はsがaから何回増加されたかで決まる. ポインタ同士の減算は間の要素の個数を返す. すなわちs-aが要素の個数である.

解答3.4と解答3.5が同じ動作をするかは、 以下のようなプログラムで確認できる.

arg.c

24行目を有効にしたプログラムと 25行目を有効にしたプログラムを別々に作成し、結果を比較する. #ifdefとmakeを使用して両方を自動的に作成することもできる.

解答3.6,3.7

解答3.7のみ示す. 0か1のみを返すように変更すれば解答3.6になる.

strcon.c

外側のforループでs2の各文字についてs1の先頭文字と一致するかを判定し、 一致する文字があればその位置(i2)を基準にして、 内側のforループでs1全体について一致を判定している. すなわちs1[i1]が0(文字列終端)に達するまでs1[i1]とs2[i2+i1]以降が すべて一致すれば(13行目)、s1がs2に含まれることになる. 一致しなければi2を変更してこれを繰り返す.