はじめての C

C programming note*1
center() は、タブや スペースのような 空白が 文字列の 前後に 含まれていると、うまく 中央揃いには なりません。 そこで 少し コードを 追加していきます。
まず、文字コードが 空白か 否かを チェックする マクロを つくっておきます。 このマクロは 2つの 関数で 条件判定に 使われるので、main() の 前に 定義します。

#define ISBLANK(c) ((c) == ' ' || (c) == '\t')
はじめに、文字列の 前の 空白を とり除くための 関数を つくります。
void remove_pre_blank(char *buf)
{
int n;
char *p;
char *q;

for (p = buf; ISBLANK(*p); p++)
;

q = buf;
n = strlen(p) + 1;
while (n--)
*q++ = *p++;
}

(さっそく、null statement が 現れた)
この null statement が どんな 働きを するのか というと、

remove_pre_blank() という関数は、最初の 「透明ではない文字」 の 直前までの 空白や タブを とり除く 処理を 行なっている。

空の for文*2が あるが、ここで p という 変数が 「透明ではない文字」 の 最初を 指すことに なるように しているのが わかるだろう。

for文の 初期化の部分で buf の 先頭を 指すようにし、条件判定のところで ISBLANK という マクロを 使って 「透明な文字で ある間」 くり返すようにし、再初期化の文で ポインタを 1つずつ ずらすことによって それを 行なっている。(p139)

ここでいう 初期化、条件判定、再初期化 というのは for の カッコの中にある 3つの文、

1. くり返しの前に 1回だけ 実行する (初期化)

2. くり返しの 条件

3. 毎回の 末尾に 1回ずつ 実行する (再初期化)

のこと。
マクロの ISBLANK は *p が 空白や タブだと 0 以外を 返すので (条件文が 真) その度に ポインタの位置を 1つずつ ずらすことに なります。
ここでの p は ポインタであって 配列ではない、と 考えると 理解しやすいと 思います。
そして for文を 抜けた時点で、p は 「最初の 空白や タブではない」 配列の 先頭を 指すことに なります。

そうして その位置から 「文字列の最後まで」 の長さ (配列の個数) を strlen() で 求め、

これですね、

n = strlen(p) + 1; /* plus '\0' */

(次に) この個数分だけ 前に ずらすことによって 「前にあった 空白や タブを」 とり除くことを 実現している。(p138)

こちらです、

q = buf;
while (n--)
*q++ = *p++;
*q は buf の 先頭の文字を 表わしています。 しかし、この場合は 少し 意味が 違ってきます。

*q は q という ポインタが 指す内容の 値を 意味するが、ここは 代入文の 左辺なので、(つまり) 指す場所 そのものだ。

一方、右辺は *p で、同様に p という ポインタが 指す内容の 値なので、p が 指す場所の 内容が q が 指す場所 (この場合は 配列の先頭) に 代入されることに なる。(p151)

また、ここでの インクリメントの 意味ですが、

++ は、対象の 後ろに ついている スタイルを 使っている。 つまり その対象 (ポインタ) を 参照し終わってから インクリメントが 行なわれる。 つまり、

*q = *p;
q++;
p++;

というのと 結果は 同じになる。(p151)

つまり この while文では、

p という アドレスから 始まる 文字列を n文字分だけ q という アドレス以降に コピーしているのだ。 「なるべく 意味が わかりやすく 書く」 という 原則から はずれているように 見えるが、これは よくある 書き方であって、 ... そのまま 憶えてしまっても よい。(p145)

別の 言い方をすると、

(すなわち) ループを くり返すことにより ... 「連なっているものを、ポインタを ずらしながら どんどん コピーしていく」 ということが 可能になる。(p151)

ということです。

(これは) ただ 慣用句だと いうだけでなく、C の 文法的にも とても 合理的な 書き方なのだ。

いずれ C という 言語の コンセプトが 理解できてくれば、どれだけ 合理的な 書き方なのかが 実感できるように なるだろう。(p145)

K&R 2nd にも、でてきたような気が ...
(追記) ちょっと 訂正。

*1:「作ってわかる Cプログラミング」

*2:null statement