我有一段看起来像这样的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}。
答案 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();