Iwi*_*ist 17 c alias parameter-passing language-lawyer c11
ISO C要求托管实现调用名为的函数main
.如果程序接收到参数,它们将作为char*
指针数组接收,这是main
定义中的第二个参数int main(int argc, char* argv[])
.
ISO C还要求argv
数组指向的字符串是可修改的.
但argv
别名的元素可以相互影响吗?换句话说,可以存在i
,j
使得
0 >= i && i < argc
0 >= j && j < argc
i != j
0 < strlen(argv[i])
strlen(argv[i]) <= strlen(argv[j])
argv[i]
别名 argv[j]
在计划启动?如果是这样,argv[i][0]
也可以通过别名字符串看到写入argv[j]
.
ISO C标准的相关条款如下,但不允许我最终回答这个名义上的问题.
§5.1.2.2.1程序启动
在程序启动时调用的函数被命名
main
.该实现声明此函数没有原型.它应定义为返回类型int
且没有参数:Run Code Online (Sandbox Code Playgroud)int main(void) { /* ... */ }
或者有两个参数(这里称为
argc
和argv
,虽然可以使用任何名称,因为它们是声明它们的函数的本地名称):Run Code Online (Sandbox Code Playgroud)int main(int argc, char *argv[]) { /* ... */ }
或同等学历; 10)或以某种其他实现定义的方式.
如果声明它们,
main
函数的参数应遵循以下约束:
- 值
argc
应为非负值.argv[argc]
应为空指针.- 如果值
argc
大于零,则argv[0]
通过argv[argc-1]
包含的数组成员应包含指向字符串的指针,这些指针在程序启动之前由主机环境给出实现定义的值.目的是在程序启动之前从托管环境中的其他地方向程序提供信息.如果主机环境不能提供大写和小写字母的字符串,则实现应确保以小写形式接收字符串.- 如果值
argc
大于零,则指向的字符串argv[0]
表示程序名称;argv[0][0]
如果程序名不能从主机环境获得,则应为空字符.如果值argc
大于1,则argv[1]
through 指向的字符串argv[argc-1]
表示程序参数.- 数组指向的参数
argc
和argv
字符串argv
应由程序修改,并在程序启动和程序终止之间保留它们最后存储的值.
通过我的阅读,名义问题的答案是"是",因为它没有明确禁止,标准没有任何地方敦促或要求使用 - char* restrict*
资格argv
,但答案可能会转向解释"并保留其最后 -程序启动和程序终止之间存储的值." .
这个问题的实际意义在于,如果对它的回答确实是"是",那么希望修改字符串的便携式程序argv
必须首先执行(相当于)POSIX strdup()
以确保安全.
通过我的阅读,名义上的答案是"是",因为它没有明确禁止,标准敦促或要求使用限制合格的argv,但答案可能会转向解释"并保留其最后一个 - 程序启动和程序终止之间的存储值."
我同意标准没有明确禁止参数向量的元素成为彼此的别名.我不认为可修改性和价值保留条款与该立场相矛盾,但它们确实向我建议委员会不考虑混淆的可能性.
这个问题的实际意义在于,如果它的答案确实是"是",那么希望修改argv中的字符串的可移植程序必须首先对它们执行(相当于)POSIX strdup()以确保安全.
实际上,这正是我认为委员会甚至没有考虑这种可能性的原因.如果他们做了那么肯定他们将有至少包含一个脚注到同样的效果,要不然明确指定的参数字符串是完全不同的.
我倾向于认为这个细节没有引起委员会的注意,因为在实践中,实现确实提供了不同的字符串,而且因为程序很少修改它们的参数字符串(尽管修改argv
它本身更为常见).如果委员会同意在这个领域发布官方解释,那么我不会对他们反对混淆的可能性感到惊讶.
直到除非这样的解释被发布,但是,你是正确的,严格一致不允许你依靠先天上argv
不被混淆的元素.
它在常见的*nix平台(包括Linux和Mac OS,也可能是FreeBSD)上工作的方式是argv
指向一个包含参数字符串的单个内存区域的指针数组(仅由空终止符分隔).使用execl()
不会改变这一点 - 即使调用者多次传递相同的指针,源字符串也会被多次复制,对于相同的(即别名的)指针没有特殊的行为(一种不常见的情况,优化没有太大的好处).
但是,C不需要此实现.真正的偏执者可能希望在修改它之前复制每个字符串,如果内存有限则可能会跳过副本,并且循环argv
显示没有任何指针实际上是别名(至少在程序打算修改的那些中).除非您正在开发飞行软件等,否则这似乎过于偏执.