我一直在收到这个警告:
note: expected ‘const char **’ but argument is of type ‘char **’
Run Code Online (Sandbox Code Playgroud)
现在,我通过将它们转换为传递参数const char **
.还有其他方法我可以摆脱它吗?
Who*_*aig 50
简答
你可以安全地强制转换char **
到const char**
?不.(反正不安全),原因比你想象的要微妙得多.你能用另一种方式摆脱它吗?当然.const char*
从您的char*
值加载一组值并传递它.(或更改被调用者原型,但那就是作弊= P).
考虑以下代码,除了调用函数之外,它基本上执行您希望的所有操作.标记的线表示等效的投射点
const char *s = "Test";
char *p = NULL;
char **pp = &p; // Put address of our pointer in our pointer-to-pointer.
const char **cpp = pp; // Here: assigning char** to const char**
*cpp = s; // perfectly legal; pp and s both finish "char const"
*p = 0; // ru ro raggy
Run Code Online (Sandbox Code Playgroud)
真的盯着这个需要一段时间,而且我一开始也没看到它.@sheu做了大约24小时才能抓住它,我真的想到它已经足够长时间才能意识到他一直都是对的(我在写这篇文章之前我真的赞成了这个答案).然后我认为他错了,同时他认为他的答案不适用.事实证明我们在那次飞跃中都是错的,因为他第一次是对的,第二次我错了,现在......呃.
在VS2012和VS2010上,标记的行都将标记错误而不进行强制转换.clang会在C中用警告编译它,但是允许它(我发现它很令人惊讶).鉴于,你必须真正走出你快乐的地方来打破它,但它仍然是非常少的.
其余部分是识别指针类型,它们的常量以及等同于什么的指示.
指针与Const的长期诽谤
警告是因为char **
而且const char **
不等同(duh).为了正确,您可以修复原型(被调用者),或修复调用者(通过加载数组const char *
并传递它).但是你可以安全地将第一个到第二个进行类型转换吗?嗯....
请记住,按标准const
立即转到左侧的项目.在数据类型的最左侧声明它是语言支持的一种精确性,但通常会引入混淆或问题.作为一个经验法则,如果const
出现在紧接类型之前的十进制的最左边,它将应用于数据类型 ; 不是后续指针(如果有的话).当它出现在任何东西的右边时,它适用于立即左侧的decl-part,无论是数据类型部分还是指针部分,无论它只适用于单个部分.
以下是大量样本:
没有间接:
const char ch; // const character. must be initialized.
char const ch; // same as above
Run Code Online (Sandbox Code Playgroud)
单方向:
char *p; // p is mutable, *p is mutable
const char *p; // p is mutable, *p is const
char const *p; // same as above.
char *const p; // p is const, *p is mutable, must be initialized.
char const *const p; // p is const, *p is const, must be initialized.
Run Code Online (Sandbox Code Playgroud)
双间接:
char **p; // ptr-to-ptr-to-char
// p, *p, and **p are ALL mutable
const char **p; // ptr-to-ptr-to-const-char
// p and *p are mutable, **p is const
char const **p; // same as above
char *const *p; // ptr-to-const-ptr-to-char
// p is mutable, *p is const, **p is mutable.
char **const p; // const-ptr-to-ptr-to-char
// p is const, *p is mutable, **p is mutable.
// must be initialized.
const char **const p; // const-ptr-to-ptr-to-const-char
// p is const, *p is mutable, **p is const.
// must be initialized.
char const **const p; // same as above
char const *const *p; // ptr-to-const-ptr-to-const-char
// p is mutable, *p is const, **p is const.
const char *const *p; // same as above.
char *const *const p; // const-ptr-to-const-ptr-to-char
// p is const, *p is const, **p is mutable.
// must be initialized.
Run Code Online (Sandbox Code Playgroud)
当然谁不能离开家...
char const *const *const p; // const-ptr-to-const-ptr-to-const-char
// everything is const.
// must be initialized.
const char *const *const p; // same as above
Run Code Online (Sandbox Code Playgroud)
那么这对您的问题有何影响?在C中编译该代码时,如果没有强制转换,您将收到编译器警告(如果编译时会出错-Werror
).在C++中进行编译时,由于参数签名不匹配,您只会出错.但为什么?
因为这些没有直接的等价:
const char **p; // ptr-to-ptr-to-const-char
// p and *p are mutable **p is const
char **p; // ptr-to-ptr-to-char
// p, *p, and **p are all mutable
Run Code Online (Sandbox Code Playgroud)
使用clang进行编译时,C中的确切警告如下:
main.c:15:9:传递
char **
给const char **
嵌套指针类型中的discards限定符类型的参数.
另一方面,VS2010和VS2012都抛出错误:
错误C2440:'初始化':无法从'char**'转换为'const char**'
这看起来很奇怪,但VS实际上更正确(奇迹永远不会停止).
这很有道理.紧跟在类型声明中的事实是,第一个不允许修改最终数据,第二个确实如此.从上面我们知道char **
和const char **
(又名char const **
)不一样.在一个的底部是指向a的指针const char
,而另一个指针指向char
.
she*_*heu 35
编辑:我甚至回答了错误的问题.我的回答完全无关紧要!请不要理我
编辑2:在绅士提问者澄清他的问题之后,事实证明我的答案实际上是相关的. 这就是生活.
这是一个有趣的C,如果你认真考虑它,这是有道理的.
基本上,转换:
char** ptr;
const char** const_ptr;
const_ptr = ptr; // <-- BAD!
Run Code Online (Sandbox Code Playgroud)
不被允许.
为什么,你可能会问?"我正在制作更多的东西!这显然是件好事!"
好吧,想一想.如果允许,那么:
const char c = 'A';
char* ptr;
const char** const_ptr = &ptr; // <-- ILLEGAL, but what if this were legal?
*const_ptr = &c;
*ptr = 'B'; // <- you just assigned to "const char c" above.
Run Code Online (Sandbox Code Playgroud)
BAM你已经死了 所以不行 :-)