Using the _Generic
feature in C11, how do you deal with string literals?
For instance:
#include <stdio.h>
#define foo(x) _Generic((x), char *: puts(x))
int main()
{
foo("Hello, world!");
return 0;
}
gives this error on clang:
controlling expression type 'char [14]' not compatible with any generic association type
Replacing char *
with char[]
gives me
error: type 'char []' in generic association incomplete
The only ways (to my knowledge) of getting this to compile are:
- Cast the string literal to an appropriate type. This is ugly and (in my view) defeats the point of
_Generic
in the first place.
- Use
char[14]
as the type specifier. You have got to be kidding me...
My assumption was that arrays would decay to pointers when passed to _Generic
, but evidently not. So, how do I use _Generic
with string literals? Are those the only two options?
I'm using clang 3.2 on Debian. Unfortunately, it's the only compiler I have access to that supports this feature, so I can't tell if it's a compiler bug or not.
Here is a solution:
#include <stdio.h>
#define foo(x) _Generic((0,x), char*: puts(x))
int main()
{
foo("Hello, world!");
return 0;
}
This compiles and produces:
$ clang t.c && ./a.out
Hello, world!
It is somewhat lame, but I did not find any better way to make x
decay to a pointer to char nor to match its type in the fuzzy fashion that you require, with Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn).
According to this blog post by Jens Gusted, GCC's behavior is different (in GCC, strings automatically decay to pointer in a _Generic
context, apparently).
By the way, in C, the type of a string literal is array of char
, not of const char
. Rejecting char []
as type-name in a generic-association is not a compiler bug:
A generic selection shall have no more than one default generic association. The type name in a generic association shall specify a complete object type other than a variably modified type. (6.5.1.1:2 with my emphasis)
I have figured out a way to avoid using the clever (0,x)
trick.
If you use a string literal the type is char[s]
, where s
is the size of the string literal.
How do you get that size?, use sizeof
operator:
#include <stdio.h>
#define Test( x ) _Generic( ( x ) , char*: puts , \
const char*: puts , \
const char[sizeof( x )]: puts , \
char[sizeof( x )]: puts )( x )
int main(void)
{
char str[] = "This" ;
Test( str ) ;
Test( "works" ) ;
char str2[10] = "!!!" ;
Test( str2 ) ;
return 0;
}
I tried compiling it with clang and Pelles and it worked.
The only problem you still have to cast variable length arrays.
After trying some more I found another analogue way of doing what
Pascal Cuoq did, use &*
operators:
#include <stdio.h>
#define foo(x) _Generic( ( &*(x) ), char*: puts , const char*: puts )( x )
int main()
{
foo("Hello, world!");
return 0;
}