这个问题在这里已经有了答案:
Is argv[n] writable?
(4 个回答)
5年前关闭。
最近(2016 年 1 月,以防问题持续很长时间)我们遇到了问题 Are the strings in argv modifiable? .
在评论区给this回答,我们(@2501 和我)争论它是否真的是 字符串 (示例字符是 **argv
)可修改或 指向字符串的指针 (示例指针是 *argv
)。
适当的标准引用来自 C11 标准草案 N1570,§5.1.2.2.1/2:
The parameters
argc
andargv
and the strings pointed to by theargv
array shall be modifiable by the program, and retain their last-stored values between program startup and program termination.
指向由
argv
指向的字符串的指针也是如此。可修改?
最佳答案
正如问题中引用的 OP 一样,C11 标准明确指出 argc
和 argv
变量,以及 argv
指向的字符串数组,可修改。这些指针是否可修改,是手头的问题。该标准似乎没有以一种或另一种方式明确说明它。
关于标准中的措辞,有两个关键点需要注意:
int main(int argc, char *const argv[])
来说明这一点。 , 如 haccks mentioned在这个问题的另一个答案中。事实上,标准中没有任何地方是
const
与 argv
相关的提及似乎是故意的。即缺少const
似乎不是可选的,而是由标准规定的。 argv
始终是一个数组。修改数组是指修改其成员。因此,标准中的措辞显然是指修改argv
中的成员。数组,当它指出 argv
是可修改的。另一方面,C 中的数组参数(基于 C11 草案 N1570,第 6.7.6.3p7 节)“应调整为‘限定类型的指针’”。因此,下面的代码,
int foo(int x[2], int y[2])
{
if (x[0] > y[0])
x = y;
return x[1];
}
是有效的 C11,因为
x
和 y
调整为 int *x
和 int *y
, 分别。 (这也在 C11 草案 N1570 的第 6.3.2.1p3 节中重申:“......数组......被转换为一个类型为'pointer to type'的表达式,它指向数组的初始元素......”。 )显然,如果
x
就不是这样了。和 y
被声明为局部或全局数组,而不是函数参数。 就语言律师主义而言,我会说标准并没有以一种或另一种方式说明它,尽管它暗示指针也应该是可修改的。因此,作为对 OP 的回答:两者 .
在实践中,
argv
中的指针有很长的传统。数组可修改。许多库都有初始化函数,这些函数采用指向 argc
的指针。和指向 argv
的指针数组,其中一些确实修改了 argv
中的指针数组(删除特定于库的选项);例如 GTK+ gtk_init()
和 MPI_Init()
(尽管至少 OpenMPI 明确声明它不会检查或修改它们)。查找参数声明 (int *argc, char ***argv)
;这样做的唯一原因——假设意图是从 main()
调用的使用 (&argc, &argv)
-- 是修改指针,从命令行参数中解析和删除库特定的命令行参数,修改两者argc
以及 argv
中的指针如所须。(我最初指出 POSIX 中的
getopt()
设施依赖于可修改的指针——该功能可追溯到 1980 年,被大多数 Unix 风格采用,并于 1997 年在 POSIX.2 中标准化——但这是不正确的,正如乔纳森Leffler 在评论中指出:POSIX getopt()
不会修改实际的指针;只有 GNU getopt()
会,而且只有在没有设置 POSIXLY_CORRECT
环境变量时才会修改。GNU getopt_long()
和 BSD getopt_long()
都会修改指针,除非 POSIXLY_CORRECT
被设置,但与 getopt()
相比,它们更年轻,更不广泛。)在Unix领域,修改
argv[]
指向的字符串的内容被认为是“可移植的”。数组,并使修改后的字符串在进程列表中可见。 DJB 的 daemontools 软件包 readproctitle 中的一个示例说明了这一点是如何有用的。 . (请注意,字符串必须就地修改,不能扩展,以便更改在进程列表中可见。)所有这些都表明了一个非常悠久的传统,基本上几乎从 C 作为一种编程语言诞生以来,并且肯定在 C 的标准化之前,处理
argc
, argv
,指针在argv
数组,以及这些指针指向的字符串的内容,作为可修改的。因为 C 标准的意图不是定义新行为,而是将跨实现的现有行为编码(以提高可移植性和可靠性等),所以似乎可以安全地假设部分标准编写者无意中遗漏了在
argv
中明确指定指针数组为可修改的。其他任何事情都会打破传统,并明确违反 POSIX 标准(该标准也旨在促进跨系统的可移植性,并扩展未包含在 ISO C 标准中的 C 功能)。
关于c - argv 中指向字符串的指针是否可修改?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35105918/