web-dev-qa-db-ja.com

Cのコマンドライン引数 `argv`のタイプは何ですか?

コマンドライン引数argvに関するCプライマープラスのセクションを読んでいますが、この文章を理解することが困難です。

それは言う、

プログラムはコマンドライン文字列をメモリに格納し、各文字列のアドレスをポインタの配列に格納します。この配列のアドレスは、2番目の引数に格納されます。慣例により、このポインタへのポインタは、引数値に対してargvと呼ばれます。

これは、コマンドライン文字列がcharの配列へのポインタの配列としてメモリに格納されることを意味しますか?

15
Jin

_C11_からの直接引用、§5.1.2.2.1/ p2章、プログラムの起動、(鉱山を強調)

int main(int argc, char *argv[]) { /* ... */ }

[...] argcの値がゼロより大きい場合、配列メンバー_argv[0]_から_argv[argc-1]_までは、文字列へのポインターを含む、[です。 ..]

そして

[...]とargv配列が指す文字列[...]

したがって、基本的に、argvは文字列の配列の最初の要素へのポインタです 注意。これは代替形式からより明確にすることができます。

int main(int argc, char **argv) { /* ... */ }

これを、nullで終了するchar配列の最初の要素へのポインターの配列の最初の要素へのポインターとして言い換えることができますが、私は文字列にこだわりたいと思います


注意:

上記の回答で「配列の最初の要素へのポインタ」の使用を明確にするために、§6.3.2.1/ p3に従います。

sizeof演算子、__Alignof_演算子、または単項_&_演算子のオペランドである場合、または配列の初期化に使用される文字列リテラルである場合を除いて、anタイプ ''タイプの配列 ''を持つ式は、タイプ ''タイプへのポインター ''という式に変換されます配列オブジェクトの初期要素を指しますであり、左辺値ではありません。 [...]

15
Sourav Ghosh

argvはタイプchar **配列ではありませんcharへのポインターへのポインターです。コマンドライン引数はメモリに格納され、各メモリ位置のアドレスは配列に格納されます。この配列は、charへのポインターの配列です。 argvは、この配列の最初の要素を指します。

いくつか
配列
 
 + ------- + + ------ + ------ + ---- --------- + ------ + 
 argv ----------> | | | | | | | 
 | 0x100 + ------> | | | 。 。 。 。 。 。 | |プログラム名1
 0x900 | | | | | | | 
 | | + ------ + ------ + ------------- + ------ + 
 + ------- + 0x100 0x101 
 | | + ------ + ------ + ------------- + ------ + 
 | 0x205 | | | | | | 
 0x904 | + ------> | | | 。 。 。 。 。 。 | |引数1
 | | 。 | | | | | 
 + ------- + + ------ + ------ + ------------- + ------ + 
 | 。 | 。 0x205 0x206 
 | 。 | 
 | 。 | 。
 | 。 | 
 + ------- +。 + ------ + ------ + ------------- + ------ + 
 | | | | | | | 
 | 0x501 + ------> | | | 。 。 。 。 。 。 | |引数argc-1
 | | | | | | | 
 + ------- + + ------ + ------ + ------------- + ------ + 
 | | 0x501 0x502 
 | NULL | 
 | | 
 + ------- + 
 
 
0xXXXはメモリアドレスを表します

1.ほとんどの場合argv[0]はプログラム名を表しますが、プログラム名がホスト環境から利用できない場合はargv[0][0]はヌル文字を表します。

23
haccks

このスレッドは、このような列車事故です。ここに状況があります:

  • タイプargc+1char *要素を持つ配列があります。
  • argvは、その配列の最初の要素を指します。
  • argcchar型の他、さまざまな長さの配列があり、コマンドライン引数を表すnullで終了する文字列が含まれています。
  • ポインターの配列の要素はそれぞれ、charの配列の1つの最初の文字を指します。ポインタの配列の最後の要素を除いて、これはnullポインタです。

「Xの配列へのポインタ」を「Xの配列の最初の要素へのポインタ」を意味するように書く人もいます。コンテキストとタイプを使用して、実際に意味があるかどうかを判断する必要があります。

11
M.M

argvは、文字へのポインターの配列です。

次のコードは、argvの値、argvの内容を表示し、argvの内容が指すメモリでメモリダンプを実行します。うまくいけば、これは間接の意味を明らかにします。

#include <stdio.h>
#include <stdarg.h>

print_memory(char * print_me)
{
    char * p;
    for (p = print_me; *p != '\0'; ++p)
    {
        printf ("%p: %c\n", p, *p);
    }

    // Print the '\0' for good measure
    printf ("%p: %c\n", p, *p);

}

int main (int argc, char ** argv) {
    int i;

    // Print argv
    printf ("argv: %p\n", argv);
    printf ("\n");

    // Print the values of argv
    for (i = 0; i < argc; ++i)
    {
        printf ("argv[%d]: %p\n", i, argv[i]);
    }
    // Print the NULL for good measure
    printf ("argv[%d]: %p\n", i, argv[i]);
    printf ("\n");

    // Print the values of the memory pointed at by argv
    for (i = 0; i < argc; ++i)
    {
        print_memory(argv[i]);
    }

    return 0;
}

サンプル実行:

$ ./a.out Hello World!
argv: ffbfefd4

argv[0]: ffbff12c
argv[1]: ffbff134
argv[2]: ffbff13a
argv[3]: 0

ffbff12c: .
ffbff12d: /
ffbff12e: a
ffbff12f: .
ffbff130: o
ffbff131: u
ffbff132: t
ffbff133:
ffbff134: H
ffbff135: e
ffbff136: l
ffbff137: l
ffbff138: o
ffbff139:
ffbff13a: W
ffbff13b: o
ffbff13c: r
ffbff13d: l
ffbff13e: d
ffbff13f: !
ffbff140:

$

コマンドライン引数を含むffbff12cからffbff140までのこの大きな連続した配列があります(これは、標準で連続していることは保証されていませんが、通常の方法です)。 argvにはその配列へのポインタが含まれているだけなので、単語を探す場所がわかります。

argvはポインターです...ポインターへ...文字へ

0
QuestionC

はい、正確に。

argvchar**またはchar*[]、または単にchar *ポインタの配列。

したがって、argv [0]はchar*(文字列)およびargv[0][0]charです。

0
blue112

はい。

argvのタイプはchar**、つまりcharへのポインターへのポインター。基本的に、char*を文字列にすると、argvは文字列の配列へのポインタになります。

0
Peter K