C11 5.1.2.2.1 / 2说:
参数
argc
和argv
以及argv
数组指向的字符串应 可以由程序修改,并在程序之间保留它们最后存储的值 启动和程序终止。
我对此的解释是它指定:
int main(int argc, char **argv)
{
if ( argv[0][0] )
argv[0][0] = 'x'; // OK
char *q;
argv = &q; // OK
}
然而它没有说什么:
int main(int argc, char **argv)
{
char buf[20];
argv[0] = buf;
}
是否允许argv[0] = buf;
?
我可以看到(至少)两个可能的论点:
argv
和argv[x][y]
但不是argv[x]
,所以意图是它不可修改argv
是指向非const
个对象的指针,所以在没有相反的特定措辞的情况下,我们应该假设它们是可修改的对象。答案 0 :(得分:6)
IMO,像argv[1] = "123";
这样的代码是UB。
“参数argc和argv以及argv数组指向的字符串应该是 可以由程序修改,并在程序之间保留它们最后存储的值 启动和程序终止。“C11dr§5.1.2.2.12
回想一下,{C}创建后const
进入C多年。
就像char *s = "abc";
const char *s = "abc";
一样有效。不需要const
,因为引入const
会过多地破坏现有代码。
同样,即使今天argv
应被视为char * const argv[]
或其他一些签名const
,const
中缺少char *argv[]
也无法完成指定const
,argv
或argv[]
的{{1}} - 需求。 argv[][]
- 需要需要由规范驱动。
从我的阅读中,由于规范在这个问题上没有提及,所以它是UB。
本国际标准中未明确的行为在“未定义的行为”或“省略任何明确的行为定义”“§42
中表示
[编辑]:
const
是一个非常特殊的函数C.在main()
中可能允许或不允许其他函数允许的内容。 C规范详细说明了给出了不需要的签名main()
的参数。与C中的其他函数不同,int argc, char *argv[]
可以具有备用签名main()
,也可能具有其他签名。 int main(void)
不可重入。由于C规范不再详细说明可以修改的内容:main()
,argc
,argv
,因此问argv[][]
是否可修改是合理的从规范中省略代码可以。
考虑到argv[]
的特殊性和省略指定main()
可修改,保守的程序员会将此灰色视为UB,等待未来的C规范澄清。
如果argv[]
在给定平台上可修改,则argv[i]
的范围当然不应超过i
。
由于“argc-1
应为空指针”,因此将argv[argc]
分配给argv[argc]
以外的其他内容似乎是违规行为。
尽管字符串是可修改的,但代码不应超过原始字符串的长度。
NULL
答案 1 :(得分:0)
argc
只是一个int
,可以不受任何限制地修改。
argv
是可修改的char **
。这意味着argv[i] = x
有效。但它没有说argv[i]
本身可以修改的任何内容。所以argv[i][j] = c
会导致未定义的行为。
C标准库的getopt
函数确实修改了argc和argv,但从不修改实际的char数组。
答案 2 :(得分:-1)
明确提到argv
和argv[x][x]
是可修改的。如果argv
是可修改的,那么它可以指向char
数组的另一个第一个元素,因此argv[x]
可以指向另一个字符串的第一个元素。最终argv[x]
也可以修改,这可能是没有必要在标准中明确提及它的原因。
答案 3 :(得分:-1)
答案是argv是一个数组,是的,它的内容是可修改的。
密钥在同一部分中较早:
如果argc的值大于零,则数组成员argv [0]通过 argv [argc-1] inclusive应包含指向字符串的指针 程序启动前主机环境实现定义的值。
很明显,argv被认为是一个特定长度的数组(argc)。然后* argv是指向该数组的指针,已经衰减为指针。
在此上下文中,请注意“argv应该是可修改的......并保留其内容'明确地希望该数组的内容可以修改。
我承认措辞中仍然存在一些含糊之处,特别是如果修改了argc会发生什么。
为了清楚起见,我所说的是我将这种语言理解为含义:
[argv [array]的内容和argv数组指向的字符串应该是可修改的......
因此,数组中的指针和它们指向的字符串都在读写内存中,通过更改它们不会造成任何损害,并且两者都会在程序的生命周期中保留它们的值。我希望在所有主要的C / C ++运行时库实现中都能找到这种行为,毫无例外。这不是UB。
模棱两可的是提到了argc。很难想象argc(看起来只是一个局部函数参数)的值无法改变的任何目的或任何实现,为什么要提到它呢?标准清楚地说明一个函数可以改变其参数的值,那么为什么在这方面特别处理argc呢?正是这种意外提到的argc引发了对argv的这种担忧,否则它将无法通过。从句子中删除argc,模糊性消失。