投稿されたコードは、次のアルゴリズムを使用します。
- 行 7 : 文字列の最後の文字へのポインターを設定し
t
ます (注: ユーザーが 99 文字未満の文字列を入力した場合は改行文字になります)。-1
は、終端の nil-char から 1 文字戻すことです。
- 行 8 ~ 10 : これは反転レポート ループのコアです。ポインタ
t
は、文字列の先頭にあるアドレスに対して繰り返しテストされます。t
条件句は、値 (アドレス) が文字列の開始アドレス以上かどうかを確認します。である限り、ループ本体に入り、 に保持されているアドレスに現在存在する文字がt
経由で stdout に送信されprintf()
ます。のアドレスt
は 1 種類の幅 (1 バイトのほとんどすべてのシステムでは 1 バイトchar
) だけ減分され、ループが繰り返されます。前にt
アドレスが含まれている場合にのみ、ループが中断されます (注: これは標準の範囲内ではありません。理由については以下を参照してください)。 s
このループについて知っておくべきことがあります (作成者でない場合は、作成者に指摘する必要があります)。最終的なポインター比較は標準に準拠していません。標準では、null 以外の like-type ポインター間の比較は、有効なシーケンスのベース アドレス (charinput
このコードでは、 によってパラメーター化されたアドレス) から、割り当てられたメモリ領域を超えるs
1 つの型要素まで有効であると指定されています。t
このコードはと比較され、が「少ない」s
場合にのみループが中断されます。しかし、が s より小さいt
とすぐに、その値は に対して合法的に範囲比較できなくなります。標準によれば、これは、t
s
t
charinput
charinput
メモリ ブロックのサイズを 1 回通過します。
これを正しく行う 1 つの方法は次のとおりです。
t = s + len;
while (t-- > s)
printf("%c", *t);
編集: Paul Hankin から提案された後の標準への旅の後、以前のコードは見過ごされた UB 状態を説明するために書き直されました。更新されたコードは次のとおりです。
t = s + len;
while (t != s)
printf("%c", *--t);
これは、長さゼロの文字列でも機能します。仕組みは次のとおりです。
t
文字列の終端のヌル文字のアドレスに設定されます。
t
ループに入ります。のアドレスが のベース アドレスと等しくない限り、この状態が続きますs
。
- をデクリメント
t
し、結果のアドレスを逆参照して現在の文字を取得し、結果を に送信しprintf
ます。
- 次の反復のためにループします。