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

时间:2009-11-08 11:06:50

标签: c gcc casting pointers char

我有一段看起来像这样的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 * ) bar()的定义。定义const中的(const char( * )[2])引用数组的元素,而不是指向数组的指针。此类型定义本质上是一个数组,当由void指针表示时,不是 const。真正的答案是( const void * )在投向cons时失去(const char ( * )[2]) t {ne}。

5 个答案:

答案 0 :(得分:6)

其他几个人已经说明了正确的演员表,但它会产生spurious warning。 该警告来自C标准中可能bug,或(取决于您的解释)GCC应特别处理的案例。我相信const限定符可以安全无误地提升到数组类型。您可以使用-Wno-cast-qual删除该警告,但这当然会消除您实际关注的案例的警告。

详细说明,类型const char (*)[2]表示“指向const char”的数组(长度为2)的指针。数组未标记const,只是数组的元素。与类型const void *进行比较时,编译器注意到后者是指向const的指针,而前者不是,因此生成警告。 C标准无法将数组标记为const,即使const数组等同于const数组。

答案 1 :(得分:3)

尝试:

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

编辑,但如果bar返回指向const指针的const数组的指针作为问题标题提示,那么如果您指定一个变量,则不需要强制转换类型:

char* const* foo = bar();

答案 2 :(得分:3)

最新版演员的警告问题具有历史根源。您知道C语言(以及C ++)正确禁止T** -> const T**转换。这是正确的,因为允许这种转换会为某些细微违反const-correctness规则的行为开辟道路(可以在任何自尊的常见问题解答中找到)。

但是,C语言也禁止T** -> const T* const*转换。这与允许此转换的C ++不同。 (这种转换不违反常量。)这一直被认为是C语言规范中的“设计缺陷”。这个缺陷已经在C ++中“修复”了,但它仍然存在于C中(即使在C99中)。坦率地说,我不知道为什么它在C99中保持不变。该缺陷的“后果”之一(或者更准确地说,是处理常量正确性的方法)是在C语言中,T (*)[N] -> const T (*)[N]转换仍然是被禁止的,即使它对const正确性没有固有的威胁

我无法重现您使用我的GCC版本发出的警告。但如果你得到它,它似乎只是同一意识形态的另一个结果。如果您考虑到显式转换运算符请求转换,则GCC警告完全没有道理。您可以尝试使用链式转换

来解决警告问题
const char (*foo)[2] = (const char (*)[2]) (void *) bar();

答案 3 :(得分:1)

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

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

答案 4 :(得分:0)

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