アダムローゼンフィールドの選択された答えは間違っています。クーバードの答えも。そのため、私は両方の回答に反対票を投じました。
Adam Markowitzの解釈*lineptr++
は正しいですが、これが合法的なC99コードであるかどうかという主な質問には答えていません。トムフューチャーだけがそうします。残念ながら、彼は説明していません*lineptr++
。私は彼らにそれぞれポイントを与えました。
つまり、lineptr
は変数であり、ポインタとして操作できます。したがって、ポインタをインクリメントすることは合法です。
lineptr
文字のシーケンスへのポインタのシーケンスへのポインタです。つまり、文字列配列の最初の文字列へのポインタです。コードによると、文字列はnull('\ 0')で終了するcharシーケンスであると想定できます。 nlines
配列内の文字列の数です。
whileテスト式はnlines-- > 0
です。nlines--
はポストデクリメントです(--
変数の右側にあるため)。したがって、テストが実行された後、テスト結果に関係なく実行されます。
したがって、nlines
引数として指定された値がであった0
場合、テストが最初に実行され、false
;が返されます。ループ内の命令は実行されません。nlines
はとにかくデクリメントされるので、ループnlines
後の値は。になることに注意してください。while
-1
の場合nlines == 1
、テストは戻りtrue
、nlines
デクリメントされます。ループ内の命令は1回実行されます。これらの命令が実行されている間、の値nlines
は。であることに注意してください0
。テストを再度実行すると、の場合に戻りnlines == 0
ます。
printf
命令は式を使用します*lineptr++
。これは、ポインターのポストインクリメントです(++
変数の右側にあります)。これは、式が最初に評価され、使用後にインクリメントが実行されることを意味します。したがって、最初の実行printf
で、文字列配列の最初の要素のコピーを受け取ります。これは、文字列の最初の文字へのポインタです。その後lineptr
のみインクリメントされます。次回printf
実行されるときは、lineptr
2番目の要素をポイントし、2番目の文字列が印刷されると3番目の要素に移動します。明らかに最初の文字列を出力したいので、これは理にかなっています。Adam Rosenfieldが正しければ、最初の文字列はスキップされ、最後に最後の文字列を超えて文字列を印刷しようとしますが、これは明らかに悪いことです。
したがって、このprintf
手順は、次の2つの手順の簡潔な形式です。
printf("%s\n", *lineptr);
++lineptr; // or lineptr++, which is equivalent but not as good. lineptr += 1; is ok too.
経験則として、プレインクリメントとポストインクリメントのアクションが同等である場合、パフォーマンス上の理由からプレインクリメントの方が望ましいことに注意してください。コンパイラはあなたのためにそれを切り替えるように注意を払います。まあ、ほとんどの場合。可能な場合はいつでも、プレオペレーター自身が良いので、常に使用されます。C ++でポストインクリメントとプレインクリメントを実装すると、その理由がより明確になります。