まず、K&Rはこの特定のスニペットに正誤表があります。
117(§5.10):検索の例では、プログラムは増分しますargv[0]
。これは特に禁止されていませんが、特に許可されていません。
さて、説明のために。
プログラムの名前prog
がで、次のように実行するとしますprog -ab -c Hello World
。a
引数を解析して、オプション、b
およびc
が指定され、およびHello
がWorld
非オプション引数であると言うことができるようにする必要があります。
argv
は型char **
です—関数の配列パラメータはポインタと同じであることに注意してください。プログラムの呼び出しでは、次のようになります。
+---+ +---+---+---+---+---+
argv ---------->| 0 |-------->| p | r | o | g | 0 |
+---+ +---+---+---+---+---+
| 1 |-------->| - | a | b | 0 |
+---+ +---+---+---+---+
| 2 |-------->| - | c | 0 |
+---+ +---+---+---+---+---+---+
| 3 |-------->| H | e | l | l | o | 0 |
+---+ +---+---+---+---+---+---+
| 4 |-------->| W | o | r | l | d | 0 |
+---+ +---+---+---+---+---+---+
| 5 |-------->NULL
+---+
ここで、argc
は5、argv[argc]
はですNULL
。最初はargv[0]
、char *
文字列を含む"prog"
です。
では(*++argv)[0]
、括弧があるため、argv
最初にインクリメントされ、次に逆参照されます。増分の効果は、そのargv ---------->
矢印を「1ブロック下」に移動して、を指すようにすること1
です。間接参照の効果は、最初のコマンドライン引数へのポインターを取得すること-ab
です。最後に、この文字列の最初の文字([0]
in (*++argv)[0]
)を取得し、それがオプションであるかどうかをテストし'-'
ます。これは、オプションの開始を示しているためです。
2番目の構成では、実際には、現在のargv[0]
ポインターが指す文字列をたどります。したがって、argv[0]
ポインタとして扱い、最初の文字を無視して(つまり'-'
、テストしたばかりのように)、他の文字を確認する必要があります。
++(argv[0])
はインクリメントargv[0]
し、最初の非-
文字へのポインタを取得し、それを逆参照すると、その文字の値が得られます。だから私たちは得る*++(argv[0])
。ただし、Cでは、[]
よりも緊密にバインドされるため++
、実際には括弧を削除して、式をとして取得できます*++argv[0]
。0
この文字が(上の画像の各行の最後の文字ボックス)になるまで処理を続けたいと思います。
表現
c = *++argv[0]
c
現在のオプションの値に割り当て、値c
は。 while(c)
はの省略形でwhile(c != 0)
あるため、このwhile(c = *++argv[0])
行は基本的に現在のオプションの値をに割り当ててc
テストし、現在のコマンドライン引数の最後に到達したかどうかを確認します。
このループの終わりに、argvは最初の非オプション引数を指します。
+---+ +---+---+---+---+---+
| 0 |-------->| p | r | o | g | 0 |
+---+ +---+---+---+---+---+
| 1 |-------->| - | a | b | 0 |
+---+ +---+---+---+---+
| 2 |-------->| - | c | 0 |
+---+ +---+---+---+---+---+---+
argv ---------->| 3 |-------->| H | e | l | l | o | 0 |
+---+ +---+---+---+---+---+---+
| 4 |-------->| W | o | r | l | d | 0 |
+---+ +---+---+---+---+---+---+
| 5 |-------->NULL
+---+
これは役に立ちますか?