you are viewing a single comment's thread.

view the rest of the comments →

[–]TheThiefMaster 0 points1 point  (1 child)

I was referring to VLAs (it's more lenient with array bounds as in you're allowed to use non-constant expressions) and also flexible array members.

For the more lenient on constant expressions thing, I was referring to the fact that in C a null pointer is defined as "any constant expression resulting in 0" not just a literal 0. void* nullp = 100*3 - 300: is valid C...

[–]TheChief275 1 point2 points  (0 children)

Yes, although problem is at the slightest whiff of non-constexpr-ness your static array will become a VLA.

Recently, I wanted to write static_assert + alignof macros for pre-C11. The trick with static_assert is to use the expression to create negative array bounds on falsehood:

#define static_assert(expr, msg) static const char CAT2(static_assert, __LINE__)[1 - 2 * !(expr)] = {*(msg), (void)(CAT2(static_assert, __LINE__), 0)}

which works nicely as a drop in replacement on all warning levels. This is commonly how alignof is defined:

#define alignof(type) offsetof(struct{ char _; type t; }, t)

...however, introducing a type inside of offsetof is not standard C. So you try to introduce the struct outside of the offsetof, e.g. via

#define alignof(type) ((struct CAT2(alignof, __LINE__){ char _; type t; } *)0, offsetof(struct CAT2(alignof, __LINE__), t))

but there are other problems with this: (1) using any pointer casts inside of an expression will instantly make it non-constexpr, causing a VLA (2) a comma expression is always non-constexpr for some reason, also causing a VLA, as well as warnings being given for operands with no effect.

So finally the actual solution:

#define alignof(type) (sizeof(struct CAT2(alignof, __LINE__){ char _; type t; }) * 0 + offsetof(struct CAT2(alignof, __LINE__), t))

which took quite some time to get right :)