Question

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:

  1. Cast the string literal to an appropriate type. This is ugly and (in my view) defeats the point of _Generic in the first place.
  2. 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.

Was it helpful?

Solution

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)

OTHER TIPS

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;
}

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top