I would like to static_assert()
that the signedness of wide character literals (L'x'
) matches that of wchar_t
.
The definition of wchar_t
is my own. (I am implementing a C standard library.) I would like to fail early, fail loud if the compiler used by a user has a different idea about wide character signedness than what is configured in the library.
Asserting a matching size of the types is easy:
static_assert( sizeof( wchar_t ) == sizeof( L'x' ), "size matches" );
For the builtin type char
, testing the signedness is easy. Assuming there is a _CHAR_IS_SIGNED
defined to either 0 or 1 somewhere,
static_assert( ( (char)-1 < 0 ) == _CHAR_IS_SIGNED, "char is signed" );
does the trick.
But wchar_t
is not a builtin type...
Is there a way to make this (static) assertion in "pure" C99 or C11, i.e. without relying on a specific compiler's extensions?
Clarification:
I "am" the library. I have to typedef
some integer type to wchar_t
.
The compiler -- not me -- defines wide character literals to some type. This type is not assigned a name by the compiler, but ideally should be identical to whatever I am using for wchar_t
, including signedness (which, AFAICT, is not specified by the standard).
I would like to assert / test the identity of these types in some way. The (type)-1 < 0
check shown for char
above does not work, because I cannot name "the type the compiler uses for literals".
You don't even need to check if compiler uses signed or unsigned type for wide char literals.
You can simply test if a type of wide char literals matches your typedef:
static_assert(_Generic(L'.', wchar_t : 1, default : 0), "blahblah");
But if you really want to get the type signedness, use something like this:
static_assert(_Generic(L'.', char : ((char)-1 < 0), signed char : 1, short : 1, int : 1, long : 1, long long : 1, default : 0) == _WIDE_CHAR_IS_SIGNED, "blahblah");
And (as @chux suggested) here is a safer version which forces a compilation error if wide characters type doesn't match any of the standard ones.
#define T(x) signed x : 1, unsigned x : 0 // Makes the code more readable
static_assert(_Generic(L'.', char : ((char)-1 < 0), T(char), T(short), T(int), T(long), T(long long)) == _WIDE_CHAR_IS_SIGNED, "blahblah");
#undef T