以下代码片段(正确)在C中发出警告,在C++中发出错误(分别使用gcc和g ++,使用版本3.4.5和4.2.1进行测试; MSVC似乎并不关心):
char **a; const char** b = a;
我能理解并接受这个.
这个问题的C++解决方案是将b更改为const char*const*,它不允许重新分配指针并阻止你绕过const-correctness(C++ FAQ).
char **a; const char* const* b = a;
但是,在纯C中,更正后的版本(使用const char*const*)仍会发出警告,我不明白为什么.有没有办法绕过这个而不使用演员?
澄清:
1)为什么这会在C中产生警告?它应该完全是const安全的,并且C++编译器似乎认识到它.
2)在说(并让编译器强制执行)我不会修改它指向的字符时,接受这个char**作为参数的正确方法是什么?例如,如果我想写一个函数:
void f(const char* const* in) { // Only reads the data from in, does not write to it }
我想在char**上调用它,参数的正确类型是什么?
编辑:感谢那些做出回应的人,特别是那些提出问题和/或跟进我的回复的人.
我已经接受了这样一个答案,即如果没有演员阵容,我想做的事情是无法完成的,无论是否应该这样做.
几年前我遇到了同样的问题,这让我感到厌烦.
C中的规则更简单说明(即它们不会列出转换char**
为的异常const char*const*
).结果,这是不允许的.使用C++标准,它们包含更多规则以允许这样的情况.
最后,它只是C标准中的一个问题.我希望下一个标准(或技术报告)能够解决这个问题.
>但是,在纯C中,这仍然会发出警告,我不明白为什么
您已经确定了问题 - 此代码不是常量."Const correct"意味着除了删除const的const_cast和C样式转换之外,你永远不能通过这些const指针或引用来修改const对象.
const-correctness-const的值在很大程度上是为了检测程序员错误.如果你将某些东西声明为const,那么你就是说你不认为它应该被修改 - 或者至少那些只能访问const版本的人不应该修改它.考虑:
void foo(const int*);
如声明,foo没有权限修改其参数指向的整数.
如果您不确定为什么您发布的代码不是const-correct,请考虑以下代码,与HappyDude的代码略有不同:
char *y; char **a = &y; // a points to y const char **b = a; // now b also points to y // const protection has been violated, because: const char x = 42; // x must never be modified *b = &x; // the type of *b is const char *, so set it // with &x which is const char* .. // .. so y is set to &x... oops; *y = 43; // y == &x... so attempting to modify const // variable. oops! undefined behavior! cout << x << endl;
非const类型只能以特定的方式转换为const类型,以防止在没有显式强制转换的情况下对数据类型的任何规避'const'.
最初声明为const的对象特别特殊 - 编译器可以假设它们永远不会改变.但是,如果'b'可以在没有强制转换的情况下赋值为'a',那么您可能会无意中尝试修改const变量.这不仅会破坏您要求编译器进行的检查,还会禁止您更改该变量值 - 它还会允许您中断编译器优化!
在一些编译器上,这将打印'42',在某些'43',以及其他编程器,程序将崩溃.
编辑补充:
HappyDude:你的评论是现货.无论是C语言还是你正在使用的C语言编译器,对于const char*const*的根本不同于C++语言对待它.也许只考虑为此源代码行静默编译器警告.
编辑删除:删除拼写错误
要被认为是兼容的,源指针应该是紧邻前向间接级别的const.所以,这会在GCC给你警告:
char **a; const char* const* b = a;
但这不会:
const char **a; const char* const* b = a;
或者,您可以投下它:
char **a; const char* const* b = (const char **)a;
你需要使用相同的强制转换来调用你提到的函数f().据我所知,在这种情况下无法进行隐式转换(C++除外).