代码之家  ›  专栏  ›  技术社区  ›  postfuturist

在C中将const void指针正确转换为const char指针数组

  •  6
  • postfuturist  · 技术社区  · 15 年前

    我有一段C代码,看起来像这样:

    const char (*foo)[2] = bar();
    

    现在 bar() 是返回 (const void *) . 我怎么正确地铸造这个 const 指针?代码从GCC生成此警告:

    "initialization discards qualifiers from pointer target type".   
    

    以下是我的一些失败尝试:

    const char (*foo)[2] = (const char *)bar();
    const char (*foo)[2] = (const void **)bar();
    

    原始代码确实有效,我只是无法通过正确地转换返回值来消除警告。

    编辑:建议:

    const char (*foo)[2] = (const char (*)[2])bar();
    

    这似乎是正确的,但GCC给出了以下警告:

    "cast discards qualifiers from pointer target type"   
    

    与原始警告几乎相同。

    编辑2:好吧,我想我明白了。真正的问题是 ( const void * ) 定义 巴尔) . 这个 康斯特 在定义中 (const char( * )[2]) 引用数组的元素,而不是指向数组的指针。此类型定义本质上是一个数组,当用 void 指针是 康斯特 . 真正的答案是 (无效常数*) 失去它 cons 当铸造到 (const char ( * )[2]) .

    5 回复  |  直到 15 年前
        1
  •  6
  •   Community dbr    7 年前

    其他一些人已经声明了正确的强制转换,但它生成了一个 spurious warning . 这个警告来自一个可能的 bug 在C标准中,或(取决于您的解释)GCC应特别处理的案例。我相信 const 限定符可以安全而明确地提升到数组类型。你可以用 -Wno-cast-qual 但这当然会消除对您真正关心的案例的警告。

    详细说明,类型 const char (*)[2] 表示“指向数组的指针(长度2) 康斯特 char “。数组未标记 康斯特 ,只是数组的元素。与类型比较时 const void * ,编译器注意到后者是指向 康斯特 如果前者不在,则生成警告。C标准不提供将数组标记为 常量 ,即使是 康斯特 数组将等价于 康斯特 .

        2
  •  3
  •   CB Bailey    15 年前

    尝试:

    const char (*foo)[2] = (const char (*)[2])bar();
    

    编辑 但是如果 bar 返回指向char指针常量数组的指针作为问题标题提示,如果分配给此类型的变量,则不需要强制转换:

    char* const* foo = bar();
    
        3
  •  3
  •   AnT stands with Russia    15 年前

    最新版本的演员表中的警告问题有着历史渊源。你知道C语言(以及C++)正确地禁止 T** -> const T** 转换。这是正确的,因为允许这种转换会为一些细微的违反常量正确性规则(可以在任何自尊心强的常见问题解答中找到)打开道路。

    但是,C语言也禁止 T** -> const T* const* 转换。这不同于C++,它允许这种转换。(这种转换不会违反常量正确性。)这在C语言规范中一直被认为是一种“设计缺陷”。这个缺陷在C++中是“固定的”,但是它仍然在C中坚持(甚至在C99中)。坦白地说,我不知道为什么在C99中它保持不变。这个缺陷(或者更准确地说,处理const正确性的方法)的一个“副作用”是在C语言中 T (*)[N] -> const T (*)[N] 转换仍然是被禁止的,即使它没有对常量正确性带来固有的威胁。

    我无法复制我的GCC版本给你的警告。但如果你明白了,这似乎只是同一意识形态的另一个后果。如果您考虑到转换是由显式转换运算符请求的,那么gcc警告是完全不合理的。您可以尝试使用链接的强制转换来绕过警告。

    const char (*foo)[2] = (const char (*)[2]) (void *) bar();
    
        4
  •  1
  •   Robert S. Barnes Antoni    15 年前

    请注意,您不需要数组维度:

    const void *bar() { 
        static const char a[10] = "abcdefghij";
        return &a[4];
    }
    
    int main() {
        const char (*foo)[2] = (const char (*)[])bar();
        return 0;
    }
    

    因为有些人可能很难理解:

    cdecl> explain const char (*foo)[2]
    declare foo as pointer to array 2 of const char
    
        5
  •  0
  •   reko_t    15 年前
    const char (*foo)[2] = (const char (*)[2])bar();