3

コマンドライン引数を文字配列に渡す 2 つの方法を見つけました。

int main (int argc, char **argv)
{
  const char *s1 = argv[0];
  char s2[256];
  strcpy(s2, argv[0]);

  printf("s1: %s\ns2: %s\n\n", s1, s2);
}

AIX システムで IBM xlc コンパイラーを使用してコンパイル

[マイプロンプト]> ./a.out

s1: ./a.out

s2: ./a.out

どちらの実装 (s1 または s2) が正しいですか? argv[0] は任意の長さにできるため、s1 は便利です。s2 では、argv[0] の長さが 256 文字未満である必要があります。

s1 がどのように/なぜ機能するのかわかりません。s1 の右側はコンパイル時に必要だと思いますが、実行時に生成されると思います。

4

6 に答える 6

3

s1 が機能する理由は、argv[0] の型がポインターであるためです。安全なアドレス (実際の値ではない) を割り当てるだけです。いかなる種類の割り当てやキャストも実行していません。

引数変数からのみ読み取る必要があるため、通常は最初のオプションを好みます。

于 2009-07-31T19:01:58.580 に答える
3

文字列を変更したくない場合は、s1 が機能します。

文字列を変更したい場合は、そのコピーを作成できます。ただし、システムがサポートしている場合は、より安全な strnlen() および strncpy() を使用する必要があります。

于 2009-07-31T19:04:17.950 に答える
1

s1 の右側はコンパイル時に必要だと思いますが、実行時に生成されると思います。

いいえ、ステートメントが発生するたびに必要です。例えば:

void f() {
   int x = 1;
   ...
}

整数 x は、コンパイル時ではなく、関数が呼び出されるたびに 1 に初期化されます。

于 2009-07-31T19:12:02.443 に答える
1

s2 には、バッファ オーバーランの影響を受けやすいという優れた特性があります。

argv[0] の値を変更する人を見てきました。場合によっては (一部の OS では) argv[0] を変更すると、変更したものとしてプログラムが ps に表示されます。

于 2009-07-31T19:12:21.710 に答える
0

特に n > 0 の argv[n] の場合は、s1 を使用します。基本的に、ユーザーは 256 文字を超える長さの引数をフォーマットし、スタック上の情報を上書きして、必要なコードを実行できます。

于 2009-07-31T19:14:10.050 に答える
0

引数を変更せずに参照するだけの場合は、s1が適切です。

何らかの方法で引数を変更する必要がある場合は、s2 の例のようにコピーを作成する必要がありますが、s2の例では、コピー先のバッファーよりも長さが長いかどうかを明示的に確認する必要があります。 . たとえば、入力として filename.jpg のような引数を取り、出力として filename.gif を保存する場合、拡張子を .jpg から .gif に変更するため、その引数のコピーを作成する必要があります。

于 2009-07-31T19:08:39.203 に答える