C11 _Generic: how to deal with string literals?
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 Gustedt, 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;
}