我正在学习C并且仍然有点绿色,但我正在学习一些课程,并且我收到编译器警告有关重复的' const'声明说明符。
违规行是;
int main(int argc, const char const *argv[])
除非我严重误解了const在参数定义中的工作方式,否则因为argv是一个我需要使用的数组;
int main(int argc, const char const **argv)
或者
int main(int argc, const char *argv[])
编译器不会抱怨这些选项中的任何一个,如果我的思路正确,两者都应该产生相同的结果,因为* argv []是一个指向数组的指针。我意识到如果argv不是一个数组,它们会有不同的含义,但是我错了它们会产生相同的结果,并且它们是正确的声明,而不是原始声明,在这种特殊情况下?
答案 0 :(得分:3)
在这一行:
int main(int argc, const char const *argv[])
你曾两次写const
。一般来说,这是C标准允许的,但无论如何你的编译器似乎都是友好和警告的。您可以忽略或禁用此警告,也可以删除其中一个const
。
但是,main
很特别:此处使用const
是非标准的。它应该是:
int main(int argc, char *argv[])
编译器可能会也可能不会接受const
的版本。它是否是实现定义的,这意味着编译器的文档应该有一个页面,讨论它接受的main
签名。
答案 1 :(得分:1)
除非我严重误解了const在参数定义中的工作方式,否则因为argv是一个我需要使用的数组
int main(int argc, const char const **argv)
或者
int main(int argc, const char *argv[])
显然,你严重误解了const
在参数定义中的工作方式。我们稍后会谈到这一点,但首先我发现main()
的允许签名是由标准指定的。允许实现支持其他签名,但符合,#34;托管"实现需要支持:
int main(void)
和
int main(int argc, char *argv[])
和等价物(C2011,5.1.2.2.1)。因此,无论所有其他考虑因素如何,都支持这些签名,并且不需要支持不等价的签名,例如const
限定符。
然后回到数组参数的问题。假设你有一个数组...
int a[4];
...你要传递给一个函数。从技术上讲,你不能这样做。在几乎所有的上下文中,特别是当它们作为函数参数出现时,数组值衰减到指针。您可以传递这样的指针,这确实很常见,但您无法传递数组本身。数组的元素类型(包括完全相同的限定符)是结果指针值的目标类型。此外,值不能是const
- 这是类型的属性。因此,编写
int a[4];
int f(int *);
f(a);
此外,请注意,您提出的方法签名都将参数argv
声明为指向const char
的指针。该类型与指向char
的指针不兼容。如果你想声明argv
本身不能改变(虽然这样做是不必要的),那么你可以把它写成
int main(int argc, char ** const argv)
,我怀疑你的编译器会接受。如果您想声明argv
数组中的指针无法通过argv
更改,那么那就是...
int main(int argc, char * const *argv)
......这也很有可能被接受。但是,您实际尝试编写的内容将argv
元素的内容声明为const
,并且这些内容不兼容。
答案 2 :(得分:1)
const
适用于其左边的内容,除非左边没有任何内容,否则它适用于其右边的内容。宣言:
int main(int argc, const char const *argv[])
将两个const
应用于相同的char
标识符,因此警告。
如果你想说argv
是一个指向常量字符的非常量指针数组,请使用:
const char * argv[]
如果你想说argv
是一个常量字符常量指针数组,请使用:
const char * const argv[]
argv
参数的正确声明只是char* argv[]
或char** argv
。根本不使用const
个说明符。具体的编译器可能允许const
变体,但标准没有定义。