我有以下方案。
#include <stdio.h>
int main(int argc, char const * const argv[], char const * const * envp) {
for (int i = 0; i < argc; i++) {
printf("argv[%d]: %s\n", i, argv[i]);
}
printf("\n");
for (int i = 0; *envp != NULL; i++, envp++) {
printf("envp[%d]: %s\n", i, *envp);
}
return 0;
}
字符串
这将按预期编译,没有警告。
如果我把envp指针设为const,把它的声明改为下面的。
char const * const * const envp
型
则编译失败,如下所示。
$ gcc -Wall main.c
main.c: In function ‘main’:
main.c:9:45: error: increment of read-only parameter ‘envp’
9 | for (int i = 0; *envp != NULL; i++, envp++) {
|
型
这对我来说是有意义的:在这个程序中,我们可以声明每个环境字符串的(第一个也是唯一的第一个?)字符值是常量,我们可以声明每个指向每个环境字符串的指针是常量,但我们不能声明char**envp是常量。
现在,我的问题是,我怎样才能以类似的方式将数组变量argv
声明为常量,从而使argv
不能被重新赋值?
也就是说,我想声明argv
,这样下面的代码会产生类似于上面的"read-only parameter ‘envp’"
错误的编译错误。我想下面的代码编译失败。这样,下面的代码编译成功。
#include <stdio.h>
int main(int argc, char const * const argv[], char const * const * envp) {
char const * const argvbad[1] = { NULL };
argv = argvbad; // I want this to be impossible
for (int i = 0; i < argc; i++) {
printf("argv[%d]: %s\n", i, argv[i]);
}
printf("\n");
for (int i = 0; *envp != NULL; i++, envp++) {
printf("envp[%d]: %s\n", i, *envp);
}
return 0;
}
型
这是一个关于数组变量的问题。我想学习如何将数组变量声明为常量,这样它们引用的数组就不能被重新赋值。
2条答案
按热度按时间wyyhbhjk1#
在参数声明中,数组可以用限定符声明,如括号内的
const
,[
和]
:字符串
当声明被自动调整,使声明的标识符成为指针时,限定符将被应用于它。以上等效于
void foo(const char * const * const argv)
。请注意,
int main(int argc, char const * const argv[], char const * const * envp)
通常不适用于main
,因为C标准在C 2018 5.1.2.2.1 1中指定了main
声明应该采用的形式。它的规范是灵活的,因为它允许实现接受额外的形式,但我不知道任何实现记录main
可能具有该形式,加上附加的限定词另一个复杂的情况是,参数上的限定符直接与函数兼容性无关。例如,这些是兼容声明:
型
这是因为C 2018 6.7.6.3 15说:
.(在确定类型兼容性和复合类型时,每个用函数或数组类型声明的参数都被视为具有调整后的类型,而每个用限定类型声明的参数都被视为具有其声明类型的非限定版本。
但是,它们并不兼容:
型
因为上面的段落仅适用于直接在参数上的限定符。这提高了
int main(int argc, char *argv[const])
是根据C 2018 5.1.2.2.1 1的main
的令人满意的声明的可能性,因为它与int main(int argc, char *argv)
兼容,因此可以满足其允许的“等效”声明。kt06eoxx2#
如果你把
envp
变成一个常量指针(指向常量数据的常量指针),不要修改它。使用索引for
循环和索引访问envp
数组:字符串
您已经在格式字符串中使用了下标表示法;在代码中也使用它。