【问题标题】:Why do I get a warning trying to pass a 'char (*c)[6]' to a function expecting a 'const char (*c)[6]'?为什么我在尝试将 'char (*c)[6]' 传递给期望 'const char (*c)[6]' 的函数时收到警告?
【发布时间】:2012-06-27 15:26:52
【问题描述】:

我知道char **const char ** 的事情(如c faq 中所述),但我看不到任何使用指向数组的指针这样做会导致数组本身的某些内容的情况实际修改过。

我的代码:

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);
}

使用 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]'

here 的问题在某种程度上是相关的,但到目前为止还没有答案。是否只是编译器偏执,摆脱警告的唯一方法是显式强制转换?还是真的有可能出问题?

【问题讨论】:

  • 很有趣,我没有收到任何警告。你用什么标志编译?编辑:clang 似乎足够聪明,不会对此发出警告,但 GCC 仍然如此。奇数。
  • Why can't I convert 'char**' to a 'const char* const*' in C? 的可能重复项(原理相同)。
  • @OliCharlesworth:是的,看起来确实是相同的理由。所以我想我很适合铸造..
  • 为什么相同的理由?这两个问题对我来说似乎非常不同(@Oli 可能会将您的评论格式化为答案,如果只是为了我)。
  • @anatolyg:正如 Oli 所说,基本原理是一样的。这个理由是,“C 标准未能定义一些 const 安全的隐式指针转换,因此在 C++ 中定义”。问题是不同的,但它们的形式都是“为什么我不能将指针类型 X 隐式转换为更恒定的类型 Y,即使这样做是 const 安全的”。只有 X 和 Y 不同,答案是相同的,相当于“因为 C 标准不会费心弄清楚什么是 const-safe 并启用它”。

标签: c arrays pointers parameters constants


【解决方案1】:

这只是 C 语言规范的一个怪癖。再比如,char **const char *const * 的转换从 const 正确性的角度来看也是安全的,但在 C 语言中是禁止的。

这种 const 正确性规则的怪癖在 C++ 语言中已“修复”,但 C 在这方面继续坚持其原始规范。

【讨论】:

  • 在我看来,在这种情况下,警告是误报,因为无法分配给数组。当然警告是正确的,但是没有它代码就无法编译。
  • @2501:在这个问题中,您在哪里看到“分配给数组”?整个事情都是关于指针分配的。 cp 都是指针,而不是数组。
  • 想想 char** , const char** 出现的问题,然后尝试用指向数组的指针重现这个问题,你会发现必须进行数组赋值。 (稍后我会发布一个示例。)
  • @2501:我没看到。 “char** to const char**”的问题对我来说已经足够明显了。流行的示例(来自常见问题解答)并不是真正的 the 问题“char** to const char**”,它只是 one 的流行说明 one 实际问题的可能后果。在这种情况下,我仍然看不到在这个转换中我应该如何看到“数组的分配”。
  • 上例中p[0]是什么类型。
【解决方案2】:

标准的第 6.5.16.1 (1) 节涵盖了常量转换:

  • 两个操作数都是指向兼容类型的合格或不合格版本的指针, 并且左边指向的类型具有所有指向的类型的限定符 对;

在这种情况下,T 看起来像 char [6],其余的要求显然成立,通过修改您的示例可以看出:

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

然而事实并非如此!这与 6.7.3 (8) 相交:

如果数组类型的规范包括任何类型限定符,则元素类型是限定的,而不是数组类型。

所以const c6 * 实际上将类型命名为const char (*)[6];也就是说,指向 const char 的数组 [6] 的指针,而不是 指向 char 的 const 数组 [6] 的指针

那么LHS指向const char[6]类型,RHS指向char[6]类型,不兼容类型,简单赋值的要求不成立。

【讨论】:

    【解决方案3】:

    其实原因很相似(char ** vs. 数组指针)。

    对于您正在尝试做的事情,以下内容就足够了(并且有效):

    void fun(const char *p)
    {
        printf("%s", p);
    }
    
    int main(int argc, char *argv[])
    {
        char a[6] = "hello";
        char *c;
    
        c = a;
    
        fun(c);
    }
    

    根据您正在尝试做的事情,可以按如下方式修改值,从而违背目的(仅作为示例):

    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);
    }
    

    【讨论】:

    • 你的例子不正确; morefun 的参数应该是 const char (*p)[6],而不是 const char *p[6]
    • 我猜 p[1] = p1 也会输出一个警告......我的意思不仅仅是写“你好”,而是要了解最初警告的原因。
    猜你喜欢
    • 2014-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-20
    • 1970-01-01
    • 2023-04-02
    • 2020-01-31
    相关资源
    最近更新 更多