在C11中指向匿名联合的指针转换是否有效?

时间:2018-07-08 11:13:32

标签: c c11

const Boo *constBoo;
Boo *nonConstBoo;

nonConstBoo = ((union {const Boo *_q; Boo *_nq;})constBoo)._nq;

以上构造在C11中是否有效,还是仅GCC / clang扩展名您可以以这种方式将指针转换为匿名联合?如果无效,还有其他方法可以使用有效的C11代码编写等效表达式吗?

目的是模拟C11兼容的C ++ const_cast,并提供一些基本的类型安全性。从const到非const指针的显式转换将触发带有-Wcast-qual选项的警告,这是不希望的。

2 个答案:

答案 0 :(得分:4)

Cast to a union是GNU C扩展。 C标准仅在标量类型(即整数,浮点数和指针;请参见6.5.4p2)中定义转换。但是,您可以做的是在现场复制创建联合(而不是强制转换),然后选择适当的成员:

typedef struct Boo Boo;
const Boo *constBoo;
Boo *nonConstBoo;

int main()
{
    nonConstBoo = (union {const Boo *_q; Boo *_nq;}){._q=constBoo}._nq;
}

以上内容应该可以工作(在C语言中,但在C ++中,您只需要访问工会的最后使用的成员,则不能),因为合格和不合格的对象必须具有相同的表示和对齐要求,并且对指向兼容类型的合格和不合格版本(6.2.5p28)的指针。

memcpy(&nonConstBoo,&constBoo,sizeof constBoo);

应该使用两种语言。

答案 1 :(得分:4)

没有,这是不合法的,原因很简单,仅允许对标量类型进行强制类型转换,C11 6.5.4“ Cast Operators”:

  

除非类型名称指定一个空类型,否则类型名称应   指定原子,合格或不合格的标量类型,以及操作数   应该具有标量类型。

您的类型是union类型,因此这是违反约束的,任何C编译器都不能接受。

如果您只想抛弃const,请使用(Boo*)constBoo。但是请注意,这样做的后果自负,拼写一个拼写会告诉编译器您假装自己知道自己在做什么。

在大多数情况下,使用此类强制转换指针时程序的行为是不确定的,很糟糕的事情可能发生。