argv [n]是否可写?

M.M*_*M.M 32 c language-lawyer

C11 5.1.2.2.1/2说:

数组指向的参数argcargv字符串argv应由程序修改,并在程序启动和程序终止之间保留它们最后存储的值.

我对此的解释是它指定:

int main(int argc, char **argv)
{
    if ( argv[0][0] )
        argv[0][0] = 'x';   // OK

    char *q;
    argv = &q;              // OK
}
Run Code Online (Sandbox Code Playgroud)

但它没有说什么:

int main(int argc, char **argv)
{
    char buf[20];
    argv[0] = buf;
}
Run Code Online (Sandbox Code Playgroud)

argv[0] = buf;允许的?

我可以看到(至少)两个可能的论点:

  • 上面的引用是故意提到的argv,argv[x][y]但不是argv[x],所以意图是它不可修改
  • argv是指向非const对象的指针,因此在没有相反的特定措辞的情况下,我们应该假设它们是可修改的对象.

Kaz*_*Kaz 7

argv数组不需要是修改的(但在实际实现中可能是可修改的)。这是一个有意的措辞,并在1998年的n849会议上得到了重申:

https://www.open-std.org/jtc1/sc22/wg14/www/docs/n849.htm

PUBLIC REVIEW COMMENT #7

[...]

Comment 10.
Category: Request for information/clarification
Committee Draft subsection: 5.1.2.2.1
Title: argc/argv modifiability, part 2
Detailed description:

Is the array of pointers to char pointed to by argv modifiable?

Response Code: Q
    This is currently implictly unspecified and the committee 
    has chosen to leave it that way.
Run Code Online (Sandbox Code Playgroud)

此外,还提出了两项​​单独的提案,分别修改和扩充措辞。两人都被拒绝了。有兴趣的读者可以通过搜索“argv”找到它们。


琐事: Kernighan 和 Ritchie 的《C 编程语言》第二版(“K&R2”)中的一个示例与此相冲突。它在第117页,相关代码行是:

while (c = *++argv[0])
Run Code Online (Sandbox Code Playgroud)

它会增加参数向量本身内部的指针以逐步遍历字符串的字符。


chu*_*ica 6

IMO,代码就像argv[1] = "123";是UB.


"参数argc和argv以及argv数组指向的字符串应该可由程序修改,并在程序启动和程序终止之间保留它们最后存储的值." C11dr§5.1.2.2.12

回想一下,const在C创作之后很多年才进入C阶段.

很像char *s = "abc";是有效的,当它应该是const char *s = "abc";.不需要const太多的需要,否则太多的现有代码将被引入const.

同样,即使argv今天,应考虑char * const argv[]或其他一些与签名const,缺乏constchar *argv[]未完成指定const的-ness需求argv,argv[]argv[][].该const-ness需求将需要在规范中来驱动.

从我的阅读中,由于规范在这个问题上保持沉默,因此它是UB.

未定义的行为在本国际标准中以"未定义的行为"或" 省略任何明确的行为定义 " 一词另有说明"§42


[编辑]:

main()是一个非常特殊的功能是C.在其他功能允许的范围内可能允许也可能不允许main().C规范详细说明了给出int argc, char *argv[]不需要的签名的参数. main()与C中的其他函数不同,它可以具有备用签名,也可能具有其他签名int main(void). main()不是可重入的.由于C时的参数超出其办法详细说一下可以修改:argc,argv,argv[][],它是合理的问题,如果argv[]是由于修改从规范断言代码可以将其忽略.

鉴于main()指定argv[]可修改的特殊性和疏忽性,保守的程序员会将此灰色视为UB,等待未来的C规范澄清.


如果argv[i]在给定平台上可以修改,那么当然i不应超过范围argc-1.

由于" argv[argc]应该是一个空指针",分配argv[argc]NULL看似违反的东西.

尽管字符串是可修改的,但代码不应超过原始字符串的长度.

char *newstr = "abc";
if (strlen(newstr) <= strlen(argv[1])) 
  strcpy(argv[1], newstr);
Run Code Online (Sandbox Code Playgroud)

  • 千真万确,楚克斯。就像我在另一个问题中提到的那样,有相当多的代码(在旧的 Unix 领域和 GNU 领域)期望“argv”数组中的指针以及指向的字符串的内容可以修改。我认为该标准“暗示”指针是可修改的,并且省略了明确的显式声明(在 C99 5.1.2.2.1p2 中)来声明它,这只是一种疏忽。另一方面,我也看不出你的回答有什么错误;我只是忍不住得出不同的结论。 (2认同)