**argv
)或指向这些字符串的指针(例如指针为*argv
).适当的标准引用来自C11标准草案N1570,§5.1.2.2.1 / 2:
所以,指向由
argc
和argv
参数以及argv
数组指向的字符串都应该可以被程序修改,并且在程序启动和终止期间保留其最后存储的值。
argv
指向的字符串的指针是否可修改呢?**argv
)或指向这些字符串的指针(例如指针为*argv
).所以,指向由
argc
和argv
参数以及argv
数组指向的字符串都应该可以被程序修改,并且在程序启动和终止期间保留其最后存储的值。
argv
指向的字符串的指针是否可修改呢?argc
和argv
变量以及被argv
数组指向的字符串是可修改的。这些指针是否可修改,是需要考虑的问题。标准似乎没有明确说明它是可修改还是不可修改的。If the pointers were supposed to be immutable, the standard could have made it clear by requiring main to be declared as int main(int argc, char *const argv[])
, as haccks mentioned in another answer to this question.
The fact that nowhere in the standard is const
mentioned in association with argv
seems deliberate. That is, the lack of const
does not seem optional, but dictated by the standard.
The standard calls argv
consistently an array. Modifying an array refers to modifying its members. Thus, it seems obvious that the wording in the standard refers to modifying the members in the argv
array, when it states that argv
is modifiable.
On the other hand, array parameters in C (based on C11 draft N1570, §6.7.6.3p7) "shall be adjusted to 'qualified pointer to type'". Thus, the following code,
int foo(int x[2], int y[2])
{
if (x[0] > y[0])
x = y;
return x[1];
}
is valid C11, since x
and y
are adjusted to int *x
and int *y
, respectively. (This is also reiterated in C11 draft N1570, §6.3.2.1p3: "... array ... is converted to an expression with type 'pointer to type' that points to the initial element of the array ...".)
Obviously, the same would not be, if x
and y
were declared as local or global arrays, not function parameters.
argv
数组的指针是可修改的,这在编程中有着悠久的传统。许多库都有初始化函数,接受指向 argc
和 argv
数组的指针,其中一些会修改 argv
数组中的指针(删除特定于库的选项),例如 GTK+ 的 gtk_init()
和 MPI_Init()
(尽管至少 OpenMPI 明确表示不检查或修改它们)。寻找参数声明 (int *argc, char ***argv)
;假设意图是使用 (&argc, &argv)
从 main()
调用,则唯一的原因是修改指针,解析并从命令行参数中删除特定于库的命令行参数,根据需要修改 argc
和 argv
中的指针。
我最初认为POSIX中的getopt()
工具依赖于可修改指针的特性--这个特性可以追溯到1980年,被大多数Unix系统采用,并在1997年被标准化为POSIX.2--但这是不正确的,正如Jonathan Leffler在评论中指出的那样:POSIX getopt()
不会修改实际的指针;只有GNU getopt()
会在POSIXLY_CORRECT
环境变量未设置时才会进行修改。无论是GNU getopt_long()
还是BSD getopt_long()
都会在没有设置POSIXLY_CORRECT
的情况下修改指针,但它们比getopt()
年轻得多,也不如后者普及。
argv []
数组指向的字符串内容被认为是“可移植”的,并且可以在进程列表中看到修改后的字符串。这种做法的一个例子是DJB的daemontools包中的readproctitle。(请注意,只有通过原地修改,而不能扩展字符串,更改才能在进程列表中显示。)argc
,argv
,argv
数组中的指针以及这些指针所指向的字符串内容视为可修改的。argv
数组中的指针为可修改是一种无意的遗漏。其他任何行为都会破坏传统,并且明显违反POSIX标准(该标准旨在促进跨系统的可移植性,并扩展了ISO C标准中未包含的C特性)。getopt()
еҮҪ数并дёҚдҫқиө–дәҺеҸҜдҝ®ж”№зҡ„argv
; GNU getopt()
еҲҷдјҡж”№еҸҳеҸӮж•°еҲ—иЎЁгҖӮ - Jonathan Lefflergetopt()
修改指针。(尽管GNU和BSD的getopt_long()
修改指针,即使它们被标记为 const
,除非设置了POSIXLY_CORRECT
环境变量。)我需要更正我的答案。 - Nominal Animalgetopt()
的错误部分(以及其他库初始化函数的签名,您可以寻找)。如果您(或任何人)发现任何其他错误,请指出。 - Nominal Animalconst
参数被反驳了,因为const
是在C语言中的main()
函数之后才添加的。通过添加const
来改变main()
的签名将会破坏现有的代码。单独对点2进行修改可能已经足够了。 - chux - Reinstate Monicachar *
,而不是 const char *
。C++ 在那方面进行了更改(自2006年左右开始),但 C 没有。 - Kazargv
中的字符串指针是否可修改?* char const *a
和 char *const a
具有不同的含义。 - hacckschar * p = "abcd"
,那么你不能执行 p[0] = 'e'
,但是你可以修改指针 p
本身。p = "Hello"
。但是,如果在某些环境中,无论如何,char * p = "abcd"
被解释为 char * const p
,那么就不可能修改 p
。 - haccks
char* str = "foo";
,而*str = 'c';
是未定义行为。因此,在这里我会把const
放在一边。 - cadanilukargv
是一个局部变量,因此无论如何都是可以修改的。但问题是关于*argv
和其他指针的。 - too honest for this siteint main(void)
和int main(int, char**)
? - cadaniluk*argv
也是UB。 (请注意,标准并未声明字符串字面值为const char []
,而只是写入它是UB。这使得字面值仅在技术上为const char []
)。 - too honest for this site