[英]What is the type of command-line argument `argv` in C?
我正在閱讀 C Primer Plus 中關於命令行參數argv
的部分,但我很難理解這句話。
它說,
該程序將命令行字符串存儲在 memory 中,並將每個字符串的地址存儲在指針數組中。 該數組的地址存儲在第二個參數中。 按照慣例,這個指向指針的指針稱為
argv
,用於參數值。
這是否意味着命令行字符串作為指向char
數組的指針數組存儲在 memory 中?
argv
的類型為char **
。 它不是一個數組 。 它是指向char
指針。 命令行參數存儲在存儲器中,每個存儲器位置的地址存儲在一個數組中。 這個數組是一個指向char
的指針數組。 argv
指向此數組的第一個元素。
Some array +-------+ +------+------+-------------+------+ argv ----------> | | | | | | | | 0x100 +------> | | | . . . . . . | | Program Name1 0x900 | | | | | | | | | +------+------+-------------+------+ +-------+ 0x100 0x101 | | +------+------+-------------+------+ | 0x205 | | | | | | 0x904 | +------> | | | . . . . . . | | Arg1 | | . | | | | | +-------+ +------+------+-------------+------+ | . | . 0x205 0x206 | . | | . | . | . | +-------+ . +------+------+-------------+------+ | | | | | | | | 0x501 +------> | | | . . . . . . | | Argargc-1 | | | | | | | +-------+ +------+------+-------------+------+ | | 0x501 0x502 | NULL | | | +-------+ 0xXXX Represents memory address
1.在大多數情況下, argv[0]
表示程序名稱,但如果主機環境中沒有程序名稱,則argv[0][0]
表示空字符。
直接引用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
運算符或一元&
運算符的操作數,或者是用於初始化數組的字符串文字,否則將具有類型''數組類型''的表達式轉換為表達式輸入''指向類型'的指針 ,指向數組對象的初始元素,而不是左值。 [...]
這個線程是這樣的火車殘骸。 情況如下:
argc+1
char *
類型的元素。 argv
指向該數組的第一個元素。 argc
其他類型為char
和各種長度的數組,包含表示命令行參數的空終止字符串。 char
數組的第一個char
; 除了指針數組的最后一個元素,它是一個空指針。 有時候人們會寫“指向X數組的指針”來表示“指向X數組的第一個元素的指針”。 您必須使用上下文和類型來確定它們是否確實意味着它。
對,就是這樣。
argv
是char**
或char*[]
,或者只是char *指針的數組。
所以argv [0]是一個char*
(一個字符串),而argv[0][0]
是一個char
。
是。
argv
的類型是char**
,即指向char
指針。 基本上,如果你認為char*
是一個字符串,那么argv
是一個指向字符串數組的指針。
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
是指針......指向字符的指針
嚴格來說,要使argv
成為數組,必須存在許多屬性。 讓我們考慮其中的一些:
¹/ null 指針不能指向任何數組,因為null 指針保證是不同於任何 object 的地址。 因此,以下代碼中的argv
不能是數組:
#include <assert.h>
int main(int argc, char *argv[]) {
if (argv) return main(0, 0);
assert(argv == 0); // argv is a null pointer, not to be dereferenced
}
²/ 分配給數組是無效的。 例如, char *argv[] = { 0 }; argv++;
char *argv[] = { 0 }; argv++;
是違反約束的,但是int main(int argc, char *argv[]) { argv++; }
int main(int argc, char *argv[]) { argv++; }
編譯並運行良好。 因此,我們必須從這一點得出結論,當聲明為參數時, argv
不是數組,而是(可能)指向數組的指針。 (這實際上與第 1 點相同,但來自不同的角度,因為使用 null 指針調用main
作為argv
實際上是重新分配argv
,這是我們無法對數組執行的操作)。
³/... 正如 C 標准所說:
sizeof 運算符的另一個用途是計算數組中元素的數量:sizeof array / sizeof array[0]
例如:
#include <assert.h>
int main(int argc, char *argv[]) {
size_t size = argc+1; // including the NULL
char *control[size];
assert(sizeof control / sizeof *control == size); // this test passes, because control is actually an array
assert(sizeof argv / sizeof *argv == size); // this test fails for all values of size != 1, indicating that argv isn't an array
}
⁴/ 一元&
地址運算符被定義為當應用於數組時,將產生不同類型的相同值,例如:
#include <assert.h>
int main(int argc, char *argv[]) {
char *control[42];
assert((void *) control == (void *) &control); // this test passes, because control is actually an array
assert((void *) argv == (void *) &argv); // this test fails, indicating that argv isn't an array
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.