我试图让参数信息变得可修改。
#include <stdio.h>
#include <stdlib.h>
int main(const int argc, const char* const argv[]) {
//argc = 1; // error: assignment of read-only parameter 'argc'
//argv[0] = "argv"; // error: assignment of read-only location '*argv'
//argv[0][0] = 'a'; // error: assignment of read-only location '**argv'
return EXIT_SUCCESS;
}
现在当我这样做时,
argv = NULL; // no compile-time error
编译器沉默。
该陈述实际上做了什么? 如何禁止我的代码执行此操作?
答案 0 :(得分:10)
嗯,首先,不要这样做。
我参考如何的现有答案,他们解释了const
可以应用的不同级别以及如何在straight pointer syntax以及"disguised as an array"-syntax。这绝对是个好消息。
但是它来了:main
非常特别。根据C标准,它没有原型,但定义应该只采用两种形式中的一种。这是原始文本,从N1570,最新草案到C11:
§5.1.2.2.1:
程序启动时调用的函数名为
main
。实施宣布否 这个功能的原型。它应定义为返回类型int
且没有 参数:
int main(void) { /* ... */ }
或者有两个参数(这里称为argc
和argv
,但可能有任何名称 使用,因为它们是声明它们的函数的本地):
int main(int argc, char *argv[]) { /* ... */ }
或等效的; 10)或其他一些实现定义的方式。
脚注10甚至解释了等效的含义:
因此,
int
可以替换为定义为int
的typedef名称,或者argv
的类型可以写为char ** argv
,等等。
但至于添加一些const
,请查看§6.7.6.1p2 :
要使两个指针类型兼容,两者都必须相同的合格并且两者都必须 是兼容类型的指针。
(强调我的)。 const
是一个类型限定符。因此const char **
与char **
兼容。您定义的main
不再符合C标准。因此,就是不要这样做。在程序中使用const
正确性,但不要尝试更改程序启动的界面。
旁注:确切地说一个 const
这里可能可以正常,因为它适用于指针本身,这只是一个函数的局部变量(因为参数在C函数调用中总是按值)。所以它不会改变函数的界面。这就是为什么在实践中,没有人喜欢添加这样的const
。调用代码是否函数修改其本地函数并不重要。
答案 1 :(得分:8)
由于这个答案已被固定在最前面,我觉得我应该指出我的答案只能解决部分问题。有关为何不以这种方式声明main
,请参见Felix Palmen's answer。
如果使用数组类型声明参数,则使用指针类型隐式替换该类型:
int main(const int argc, const char* const argv[]) {
变为
int main(const int argc, const char* const *argv) {
所以argv
是指向const char的const指针的非const指针。
argv = NULL
只是将指针设置为空指针,就像为任何其他指针指定NULL一样。这不会有任何直接可见的外部效果 - 它不会删除你的命令行或任何东西 - 但它会干扰你在程序中使用参数信息的进一步尝试。
如果您希望argv
本身为const,请将其声明为const:
int main(const int argc, const char * const * const argv) {
答案 2 :(得分:6)
您可以将const
放在数组外观指针参数的括号中,以防止重新分配给它:
int main(const int argc, const char* const argv[const]) {
人们通常不会为此烦恼。