为什么我的编译器(GCC)不会从char**
隐式转换为const char**
?
以下代码:
#include <iostream>
void print(const char** thing) {
std::cout << thing[0] << std::endl;
}
int main(int argc, char** argv) {
print(argv);
}
给出以下错误:
oi.cpp: In function ‘int main(int, char**)’:
oi.cpp:8:12: error: invalid conversion from ‘char**’ to ‘const char**’ [-fpermissive]
oi.cpp:3:6: error: initializing argument 1 of ‘void print(const char**)’ [-fpermissive]
答案 0 :(得分:17)
这样的转化可让您将const char*
放入char*
的数组中,这将是不安全的。在print
你可以做到:
thing[0] = "abc";
现在argv[0]
将指向无法修改的字符串文字,而main
期望它是非const(char*
)。因此,对于类型安全,不允许进行此转换。
答案 1 :(得分:6)
@Fred Overflow的link to the FAQ是一个完整的答案。但是(对不起马歇尔)这不是最明确的解释。我不知道我的是否更清楚,但我希望如此。
问题是,如果p
是char*
指针,那么它可以用于修改它所指向的任何内容。
如果您可以获得指向pp
但p
类型为pp
的指针char const**
,那么您可以使用pp
指定p
的地址const char
。
然后,您可以使用p
修改const char
。或者,你会认为你可以。但是const char
甚至可以在只读存储器中......
在代码中:
char const c = 'a';
char* p = 0;
char const** pp = &p; // Not allowed. :-)
*pp = &c; // p now points to c.
*p = 'b'; // Uh oh.
<小时/> 作为无法编译的代码的实用解决方案,...
#include <iostream>
void print(const char** thing) {
std::cout << thing[0] << std::endl;
}
int main(int argc, char** argv) {
print(argv); // Dang, doesn't compile!
}
只是做...
#include <iostream>
void print( char const* const* thing )
{
std::cout << thing[0] << std::endl;
}
int main( int argc, char** argv )
{
print( argv ); // OK. :-)
}
干杯&amp;第h。,
答案 2 :(得分:3)
注意,虽然
void dosmth(const char** thing);
int main(int argc, char** argv) {
dosmth(argv);
是禁止的,你可以而且应该这样做
void dosmth(const char* const* thing);
int main(int argc, char** argv) {
dosmth(argv);
无论如何,这可能是你想要的。这里的要点是thing
现在指的是const char*
数组,它本身是不可变的,引用的值char
本身是不可变的。
因此,对于“查看它,但不要更改它”方案,const char* const*
是要使用的类型。
注意:我使用了更常见的(但在我看来较差)标准,试图尽可能地留下const
修饰符。就个人而言,我建议写char const* const*
而不是const char* const*
,因为它更加简洁。
答案 3 :(得分:2)
因为它可能允许我们修改常量值。请阅读此处以了解原因:http://c-faq.com/ansi/constmismatch.html