Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is cast of pointer to anonymous union valid in C11?

Tags:

c

c11

const Boo *constBoo;
Boo *nonConstBoo;

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

Is the above construct valid in C11, or is it only GCC/clang extension that you can cast a pointer to an anonymous union in this fashion? If it is not valid, is there any other way to write an equivalent expression in valid C11 code?

The intention was to emulate C++ const_cast that would be C11 compatible and provide some rudimentary type safety. An explicit cast from const to non-const pointer will trigger a warning with -Wcast-qual option, which is undesirable.

like image 228
Filip Navara Avatar asked Jul 08 '18 11:07

Filip Navara


2 Answers

Cast to a union is a GNU C extension. The C standard only defines casts among scalar types (i.e., integers, floats, and pointers; see 6.5.4p2). What you could do, however, is copy-create the union on the spot (instead of casting to it) and then take the appropriate member:

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

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

The above should work (in C, but not C++ where you're required to access only the last used member of a union) because qualified and non-qualified objects must have the same representation and alignment requirements and the same applies to pointers to qualified and unqualified versions of compatible types (6.2.5p28).

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

should work in either language.

like image 148
PSkocik Avatar answered Nov 15 '22 03:11

PSkocik


No that is not legal for a simple reason, casts are only allowed for scalar types, C11 6.5.4 "Cast Operators":

Unless the type name specifies a void type, the type name shall specify atomic, qualified, or unqualified scalar type, and the operand shall have scalar type.

Your type is a union type so this is a constraint violation and no C compiler should ever accept this.

If you just want to cast away constness, just do so, that is use (Boo*)constBoo. But note that you do that on your own risk, casting a spell tells the compiler that you pretend that you know what you are doing.

In most of the cases, the behavior of the program is undefined when you use such casted pointers, very bad things can happen.

like image 29
Jens Gustedt Avatar answered Nov 15 '22 02:11

Jens Gustedt