简体   繁体   English

为什么我在尝试将 'char (*c)[6]' 传递给需要 'const char (*c)[6]' 的函数时收到警告?

[英]Why do I get a warning trying to pass a 'char (*c)[6]' to a function expecting a 'const char (*c)[6]'?

I know about the char ** vs const char ** thing (like described in the c faq ) but I can't see any scenario where doing so with a pointer to arrays would lead to some content inside the arrays themselves being actually modified.我知道char **const char **事情(如c faq 中所述),但我看不到任何使用指向数组的指针这样做会导致数组本身内部的某些内容被实际修改的情况。

My code:我的代码:

void fun(const char (*p)[6])
{
    printf("%s", p[0]);
}

int main(int argc, char *argv[])
{
    char a[6] = "hello";
    char (*c)[6];

    c = &a;

    fun(c);
}

gives the below output when compiled with gcc:使用 gcc 编译时给出以下输出:

test.c:17:9: warning: passing argument 1 of 'fun' from incompatible pointer type
test.c:5:10: note: expected 'const char (*)[6]' but argument is of type 'char (*)[6]'

The question here is somehow related but has no answer so far. 这里的问题某种程度上是相关的,但到目前为止还没有答案。 Is it just the compiler being paranoïd and the only way to get rid of the warning is to explicitly cast ?是否只是编译器偏执,摆脱警告的唯一方法是显式强制转换? Or is there really a chance something can go wrong ?或者真的有可能出错吗?

Const-conversion is covered by section 6.5.16.1 (1) of the standard:标准的第 6.5.16.1 (1) 节涵盖了常量转换:

  • both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed to by the left has all the qualifiers of the type pointed to by the right;两个操作数都是指向兼容类型的限定或非限定版本的指针,左侧指向的类型具有右侧指向的类型的所有限定符;

In this case it looks like T is char [6] and the rest of the requirement clearly holds, as can be seen by modifying your example:在这种情况下,看起来Tchar [6]并且其余要求显然成立,通过修改您的示例可以看出:

int main(int argc, char *argv[])
{
    typedef char c6[6];
    c6 a = "hello";
    const c6 *p = &a;
}

However this is actually not the case!然而事实并非如此! This intersects with 6.7.3 (8):这与 6.7.3 (8) 相交:

If the specification of an array type includes any type qualifiers, the element type is so qualified, not the array type.如果数组类型的规范包含任何类型限定符,则元素类型如此限定,而不是数组类型。

So const c6 * actually names the type const char (*)[6] ;所以const c6 *实际上将类型命名为const char (*)[6] ; that is, pointer to array[6] of const char , not pointer to const array[6] of char .也就是说,指向 const char 的 array[6] 的指针,而不是指向char 的const array[6] 的指针

Then the LHS points to the type const char[6] , the RHS points to the type char[6] , which are not compatible types, and the requirements for simple assignment do not hold.然后 LHS 指向类型const char[6] ,RHS 指向类型char[6] ,它们不是兼容类型,简单赋值的要求不成立。

It is just a quirk of C language specification.这只是 C 语言规范的一个怪癖。 For another example, the char ** to const char *const * conversion is also safe from the const-correctness point of view, yet it is prohibited in C.再比如,从 const 正确性的角度来看, char **const char *const *转换也是安全的,但在 C 中是被禁止的。

This quirk of const-correctness rules was "fixed" in C++ language, but C continues to stick to its original specification in this regard.这种 const 正确性规则的怪癖在 C++ 语言中是“固定的”,但 C 在这方面继续坚持其原始规范。

Actually the reasons are quite similar (char ** vs. pointer of arrays).实际上原因非常相似(char ** vs. 数组指针)。

For what you are trying to do, the following would suffice (and it works):对于您正在尝试做的事情,以下内容就足够了(并且有效):

void fun(const char *p)
{
    printf("%s", p);
}

int main(int argc, char *argv[])
{
    char a[6] = "hello";
    char *c;

    c = a;

    fun(c);
}

With what you are trying to do, it would be possible to modify the values as follows that defeats the purpose (just an example):根据您正在尝试执行的操作,可以按如下方式修改值以达到目的(只是一个示例):

void morefun(const char *p[6])
{
    char d;
    char *p1 = &d;
    p[1] = p1;
    *p1 = 'X';
    printf("\nThe char is %c\n", *p[1]);
}

int main(int argc, char *argv[])
{
    const char *d[6];

    morefun(d);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM