为什么路过的char **如为const char **生成一个警告? [英] Why does passing char** as const char** generate a warning?

查看:1272
本文介绍了为什么路过的char **如为const char **生成一个警告?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经得到这样的警告:

I've been getting this warning:

note: expected ‘const char **’ but argument is of type ‘char **’

现在,我被他们铸造传递的参数为const char ** 。有没有我可以摆脱它的任何其他方式?

For now, I'm passing the arguments by casting them to const char **. Is there any other way I can get rid of it?

推荐答案

简答

你能安全地强制转换的char ** 为const char ** 没有。 (不能安全反正),原因是更为微妙比你想象的。你能摆脱它的另一种方式?当然。负载为const char * 值的数组从的char * 的价值观和传递来代替。 (或改变被叫方的原型,但多数民众赞成作弊= P)。

Can you safely typecast char ** to const char**? No. (Not safely anyway), and the reason is far more subtle than you may think. Can you get rid of it another way? Sure. Load an array of const char* values from your char* values and pass that instead. (or change the callee prototype, but thats cheating =P).

考虑以下code,基本上做的一切你希望的除了的调用函数。标记线展示了相当的点铸

Consider the following code, which essentially does everything you're wishing except invoke a function. The marked line demonstrates the equivalent point-of-cast

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

这需要一段时间才能真正盯住这一点,诚然我没有看到它在第一任。 @sheu没有接住约24小时的扎实工作之前,我真的认为它足够长的时间来实现他始终是正确的(实际上我upvoted写这篇之前的答案)。然后,我以为他是错的,他认为他的回答是不适用的同时。原来我们的两个的错误上的飞跃,因为他是在第一时间,我错了,第二次,现在...啊。

It takes awhile to really stare at this, and admittedly I didn't see it at first either. @sheu did a solid job of catching it about 24 hours before I really thought about it long enough to realize he was right all along (and I actually upvoted that answer before writing this one). Then I thought he was wrong about the same time he thought his answer wasn't applicable. Turns out we were both wrong on that leap, because he was right the first time, I was wrong the second time, and now... ugh.

在VS2012和VS2010都将标记错误没有投标线。 将在C警告编译它,但允许它(我发现令人惊讶)。考虑到,你必须要真正走出你快乐的地方,打破它,但它仍然是没有的非破碎少。

On VS2012 and VS2010 both the marked line will flag an error without a cast. clang will compile it with a warning in C, but allow it (which I found surprising). Given, you do have to really step out of your happy place to break it, but it is still none-the-less broken.

这剩下的是找出指针类型,它们的一个常量性谩骂,什么是相当于什么。

The rest of this is a diatribe on identifying pointer types, their constness, and what is equivalent to what.

上的指针和const 龙谩骂

Long Diatribe on Pointers And Const

该警告是因为的char ** 为const char ** 是不等价的(废话)。是正确的,你也可以修复原型(被调用者),或修复主叫(通过加载为const char * 数组并传递一个)。但是,你能放心地类型转换第一到第二?嗯....

The warning is because char ** and const char ** are not equivalent (duh). To be correct, you could fix the prototype (callee), or fix the caller (by loading an array of const char * and passing that). But can you safely typecast the first to the second? Hmmm....

记住,由标准常量进入该项目立即它的的。声明它放在最左边的一个数据类型是语言支持准确,但往往介绍的困惑或问题。作为一个规则的拇指,如果常量出现在最左侧一个DECL立即类型之前,它适用于数据的键入的; 不可以后续指针(如果有的话)。当它出现的任何事情,正确的 的它适用于眼前的左DECL部分,无论是数据类型部分的的指针部分,但无论只是什么适用于的的一部分。

Remember, by the standard const goes to the item immediately to its left. Declaring it on the most-left of a data type is a nicety that the language supports, but often introduces confusion or problems. As a rule-of-thumb, if const appears on the far-left of a decl immediately before the type, it applies to the data type; not the subsequent pointer (if any). When it appears to the right of anything it applies to the immediate-left decl-part, be it a data type part or a pointer part, but no matter what it only applies to a single part.

样过多如下:

否的间接

const char ch;    // const character. must be initialized.
char const ch;    // same as above

单的间接

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.

双间接

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.

当然,谁可以离开家没有...

And of course who can leave home without...

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

那么,这怎样影响你的问题吗?当编译在C,它code,不进行强制转换(如果与 -Werror 编译或错误),你会得到一个编译器警告。当C ++编译,你只是简单的错误,因为该参数签名不匹配。但是,为什么?

So how does this affect your question? When compiling that code in C, without a cast you'll get a compiler warning (or error if compiling with -Werror). When compiling in C++, you'll just plain error because the parameter signature doesn't match. But why?

由于这些都没有直接等价:

Because these have no direct equivalence:

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

在与编译的,在C准确发出警告如下:

When compiling with clang, the exact warning in C is given as:

的main.c:15:9:传递的char ** 来的类型参数为const char ** 丢弃预选赛嵌套指针类型。

main.c:15:9: Passing char ** to parameter of type const char ** discards qualifiers in nested pointer types.

VS2010和VS2012两者,另一方面,簸一个错误:

VS2010 and VS2012 both, on the other hand, toss an error:

错误C2440:初始化:不能从转换'的char **'到'为const char **

error C2440: 'initializing' : cannot convert from 'char **' to 'const char **'

这似乎很奇怪,但实际上VS是更正确的(奇观从未停止)。

It seems odd, but VS is actually more correct (wonders never cease).

这是非常合情合理的。在类型声明坐落下来的事实是,这些第一不允许修改到最终数据,则第二确实的。从上面我们知道,的char ** 为const char ** (又名字符常量** ),是的的相同。在一个底部是一个指针为const char ,而其他有一个指向字符

And that makes perfect sense. Nestled down in the type declaration is the fact that the first of these does not allow modification to the final data, the second does. From above we know that char ** and const char ** (aka. char const **), are not the same. At the bottom of one is a pointer to a const char, while the other has a pointer to char.

这篇关于为什么路过的char **如为const char **生成一个警告?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆