问题
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.
回答1:
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)
回答2:
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;
}
回答3:
The behaviour of Clang was incorrect (C11 Defect report 481) until 3.7.1. It was fixed in Clang 3.8.0, released on March 8, 2016.
The Committee response to the DR 481 says the following:
This paper elicited a long and productive discussion. The committee agrees with the author of the
_Generic
proposal that the intent was that selecting on qualified types was explicitly to be avoided as was selecting on arrays by size. The intent of_Generic
was to give C a mechanism to somewhat express the notion of “overloaded function” found in C++, and in particular a possible mechanism for implementors to use to implement the atomic type generic functions from section 7.17.7.
来源:https://stackoverflow.com/questions/18857056/c11-generic-how-to-deal-with-string-literals