_Generic to fill some union - c

I want to use the C11 _Generic keyword to fill an union according to the static type, like:
typedef union {
double d;
long l;
const char*s;
void*p;
} ty;
#define make_ty(X) _Generic((X), \
double: (ty){.d=(X)}, \
long: (ty){.l=(X)}, \
const char*: (ty){.s=(X)}, \
default: (ty){.p=(X)})
ty from_double(double x) { return make_ty(x); }
ty from_string(const char*s) { return make_ty(s); }
ty from_long(long l) { return make_ty(l);}
but this does not compile, e.g. GCC 5.3 gives (with gcc -std=c11 -Wall):
u.c: In function ‘from_double’:
u.c:11:35: error: incompatible types when initializing type ‘const char *’
using type ‘double’
const char*: (ty){.s=(X)}, \
^
u.c:14:41: note: in expansion of macro ‘make_ty’
ty from_double(double x) { return make_ty(x); }
BTW, using gcc -std=c99 -Wall gives the same error...
Or is _Generic only useful for tgmath.h ?
I thought that _Generic chooses the expression according to the compiler-known type, so the non-sensical (ty){.s=(x)} would be ignored in from_double....
(if that did work, I would be able to "overload" make_ty according the static, compiler-known, type of the argument...)

All branches of _Generic must be valid code, just as much as in something like if (1) { here; } else { there; }. To have a solution you could take it the other way around. Define functions similar to:
inline ty from_double(double x) { return (ty){ .d = x }; }
for all your cases and then have the macro as:
#define make_ty(X) _Generic((X), \
double: from_double, \
double: from_long, \
...)(X)
With the visibility through inline compilers are actually able to optimize such code and will usually not pass through calling the function pointer.

Related

TLV Macro expansion raises warning: Assignment makes pointer from integer without a cast

My TLV structure can hold string or integer. I'm trying to create a macro that handles them both.
The example below runs as expected, but it compiles with warnings from the MACRO expansion. I understand the precompiler cannot know what type of value I'm going to assign at runtime, which is why I think it's raising the warning.
How can this little code snippet be fixed so it generates no compile warnings?
FWIW, I can code around this by not using the MACRO, but would prefer to use it if possible.
$ gcc -o simple{,.c} && ./simple
simple.c: In function ‘main’:
simple.c:25:21: warning: assignment makes pointer from integer without a cast [enabled by default]
tlv.value_str = (val); \
^
simple.c:38:3: note: in expansion of macro ‘TLV2STR_MACRO’
TLV2STR_MACRO(string, TYPE_INT, 11);
^
simple.c:28:21: warning: assignment makes integer from pointer without a cast [enabled by default]
tlv.value_int = (val); \
^
simple.c:41:3: note: in expansion of macro ‘TLV2STR_MACRO’
TLV2STR_MACRO(string, TYPE_STRING, "ELEVEN");
^
-----------------------------
INT : 11
STRING: ELEVEN
-----------------------------
#include <stdio.h>
typedef struct _tlv_s {
int type;
size_t length;
union _value {
int value_int;
char *value_str;
} value_u;
} tlv_t;
#define value_int value_u.value_int
#define value_str value_u.value_str
#define TYPE_STRING 0
#define TYPE_INT 1
#define TLV2STR_MACRO(s, t, val) { \
tlv_t tlv; \
tlv.type = (t); \
if (t == TYPE_STRING) { \
tlv.value_str = (val); \
sprintf(s, "STRING: %s", tlv.value_str); \
} else { \
tlv.value_int = (val); \
sprintf(s, "INT : %d", tlv.value_int); \
} \
}
int main(int argc, char *argv[])
{
char string[128];
printf("-----------------------------\n");
TLV2STR_MACRO(string, TYPE_INT, 11);
printf("%s\n", string);
TLV2STR_MACRO(string, TYPE_STRING, "ELEVEN");
printf("%s\n", string);
printf("-----------------------------\n");
}
How can this little code snippet be fixed so it generates no compile warnings?
You can add explicit casts.
tlv.value_str = (char*)(val); \
tlv.value_int = (int)(val); \
To your FWIW, such macro will not scale up, while it is fast to write for a toy example with two types and one use case, it will become painful and unreadable when more to come. Use virtual table with dispatch functions, keep your code readable, prefer not to use macros. I suggest removing confusing definitions #define value_int value_u.value_int and keeping your symbols within one namespace tlv_*. Do not end up with unreadable big switches, which your code seems to be going for. Prefer to use snprintf instead of sprintf.
I believe (glad to be proven otherwise) that it is not possible to pass values around as I had intended, casting them arbitrarily to string or integer.
Instead, passing pointers to values and casting the pointers is the proper way to do this. (As an aside, if this was truly a TLV implementation, it would handle any kind of structure, but this is just a dinky little app to demo the issue with passing values).
Notice that I modified the macro to accept a pointer to the value.
#include <stdio.h>
typedef struct _tlv_s {
int type;
size_t length;
union _value {
int value_int;
char *value_str;
} value_u;
} tlv_t;
#define value_int value_u.value_int
#define value_str value_u.value_str
#define TYPE_STRING 0
#define TYPE_INT 1
#define TLV2STR_MACRO(s, t, valp) { \
tlv_t tlv; \
tlv.type = (t); \
if (t == TYPE_STRING) { \
tlv.value_str = (char *)(valp); \
sprintf(s, "STRING: %s", tlv.value_str); \
} else { \
tlv.value_int = *(int *)(valp); \
sprintf(s, "INT : %d", tlv.value_int); \
} \
}
int main(int argc, char *argv[])
{
char string[128];
int val_int = 11;
printf("-----------------------------\n");
TLV2STR_MACRO(string, TYPE_INT, &val_int);
printf("%s\n", string);
TLV2STR_MACRO(string, TYPE_STRING, "ELEVEN");
printf("%s\n", string);
printf("-----------------------------\n");
}
And the output from compile and run....
$ gcc -o simple{,.c} && ./simple asdf
-----------------------------
INT : 11
STRING: ELEVEN
-----------------------------

How to define general function to take input in C using _Generic?

I was trying to define a general function to take input using _Generic in C, This is what I wrote
#include <stdio.h>
#define readlong(x) scanf("%lld",&x);
#define read(x) scanf("%lld",&x);
#define scan(x) _Generic((x), \
long long: readlong, \
default: read \
)(x)
but when I compile it using gcc test.c -std=C11 on gcc 5.3.0, I get error:
error: 'readlong' undeclared (first use in this function)
You can define your helpers to be functions instead of macros. I modified scan so that it would pass the address to the matched function.
static inline int readlong (long long *x) { return scanf("%lld", x); }
static inline int readshort (short *x) { return scanf("%hd", x); }
static inline int unknown (void) { return 0; }
#define scan(x) _Generic((x), \
long long: readlong, \
short: readshort, \
default: unknown \
)(&x)
readlong
is not the variable that you have declared. In:
#define readlong(x) scanf("%11d",&x);
you added (x). This will not let you use readlong without them.

Why is the `_Generic` keyword in my macro not working?

Probably I'm doing some very basic thing wrong here, but I just cannot figure out what that could be. I can explain my code snippet, but I think it is pretty obvious what I'm trying to do here: create a type-generic macro overload "print function" for my DynamicArray's dynarr_printf method. The question is: why isn't it working?
Thanks in advance!
ENV:
// Mac OS X 10.9.2
// Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
cc -Wall -v -g -std=c11 -I/usr/local/include -c -o build/tmp/main.o main.c
CODE:
void
__dynarr_printf(DynamicArray *dynarr,
void (*print_func)(int, void*));
#define __line_fmt__(fmt) " [%d] " fmt "\n"
static inline void
__dynarr_printf_i(int i, int *v)
{
printf(__line_fmt__("%d"), i, *v);
}
// tons of type specific functions ...
static inline void
__dynarr_printf_def(int i, void *v)
{
printf(__line_fmt__("ptr(%p)"), i, v);
}
#define __dynarr_typef(type) _Generic((type), int: __dynarr_printf_i, \
// tons of type specific funcs ...
default: __dynarr_printf_def)
#define dynarr_printf(dynarr, type) \
(__dynarr_printf(dynarr, __dynarr_typef(type)))
OUTPUT:
main.c:102:5: error: expected expression
dynarr_printf(dynarr, float);
^
./dynarr.h:168:31: note: expanded from macro 'dynarr_printf'
(__dynarr_printf(dynarr, __dynarr_typef(type)))
^
./dynarr.h:157:45: note: expanded from macro '__dynarr_typef'
#define __dynarr_typef(type) _Generic((type), int: __dynarr_printf_i, \
^
1 error generated.
The syntax of a generic selection is:
_Generic ( assignment-expression , generic-assoc-list )
(For the definition of a generic-assoc-list and more information about generic selections, see N1570 section 6.5.1.1.)
The first "operand" is an expression, not a type name. It selects on the type of that expression.
If the type is always scalar, you could change
_Generic((type), ...)
to
_Generic((type)0), ...)

How to check `typeof` for void value at compile time?

let's say that I want to have C macro that works on any type.
I'm using GCC compiler (>= 4.6) and can use GNU99 macros.
//code...
any_type_t *retVal = function_that_runs_very_long_time(a, b, &&c, **d, &e, *f);
//other code...
usage of macro for TIMER can look for example like this
//code...
any_type_t *retVal =
TIMER(
function_that_runs_very_long_time(a, b, &&c, **d, &e, *f),
"TIMING FOR VALUE <%d, %d>", a, b
);
//other code...
So TIMER has to return value of given function and print duration of its run.
There is problem with functions that have void return type.
I can obviously have two macros like TIMER_TYPE and TIMER_VOID, but I want to use single one to time function with any return value.
Thank you for suggestions.
Edited example of this TIMER macro
#define TIMER(expr, fmt_msg, ...) \
({ \
struct timeval before, after; \
uint64_t time_span; \
int time_span_sec, time_span_usec; \
gettimeofday(&before, NULL); \
typeof(expr) _timer_expr__ = (expr); \ // <- static if?
gettimeofday(&after, NULL); \
time_span = (after.tv_sec * 1000000 + after.tv_usec) \
- (before.tv_sec * 1000000 + before.tv_usec); \
time_span_sec = time_span / 1000000; \
time_span_usec = time_span % 1000000; \
TRACE(fmt_msg "\n%s : %d.%d seconds", \
#expr, time_span_sec, time_span_usec, ...); \
_timer_expr__; \
})
What an interesting question, kudos!
After few experiments, I found a solution which uses __builtin_types_compatible_p and __builtin_choose_expr intrinsics of GCC.
__builtin_types_compatible_p
Quoting GCC manual:
Built-in Function: int __builtin_types_compatible_p (type1, type2)
You can use the built-in function __builtin_types_compatible_p to determine whether two types are the same.
This built-in function returns 1 if the unqualified versions of the types type1 and type2 (which are types, not expressions) are compatible, 0 otherwise. The result of this built-in function can be used in integer constant expressions.
This built-in function ignores top level qualifiers (e.g., const, volatile). For example, int is equivalent to const int.
So here is how we can check for "voidness".
#define __type_is_void(expr) __builtin_types_compatible_p(typeof(expr), void)
__builtin_choose_expr
Built-in Function: type __builtin_choose_expr (const_exp, exp1, exp2)
You can use the built-in function __builtin_choose_expr to evaluate code depending on the value of a constant expression. This built-in function returns exp1 if const_exp, which is an integer constant expression, is nonzero. Otherwise it returns exp2.
This built-in function is analogous to the ? : operator in C, except that the expression returned has its type unaltered by promotion rules. Also, the built-in function does not evaluate the expression that is not chosen. For example, if const_exp evaluates to true, exp2 is not evaluated even if it has side-effects.
If exp1 is returned, the return type is the same as exp1's type. Similarly, if exp2 is returned, its return type is the same as exp2.
So __builtin_choose_expr intrinsic is something like a "static switch" evaluated at compile-time.
Preparation
I don't paste here your TIMER macro, but I assume it is able to split it into two versions: one for void expr and one for the rest. Here are just stubs which evaluate the expression and yield the result of the same type.
#define __DO(expr) \
({ typeof(expr) __ret; __ret = (expr); __ret; })
#define __DO_VOID(expr) \
(void) (expr)
Naive solution
Now we can statically switch between two implementations, depending on the actual type of the expression. But in fact the naive solution doesn't work, see below.
#define DO(expr) \
__builtin_choose_expr(__type_is_void(expr), \
__DO_VOID(expr), \
__DO(expr)) # won't work
Attempt to compile this code passing a void expression gives the following error:
test.c:28:9: error: variable or field ‘__ret’ declared void
test.c:28:9: error: void value not ignored as it ought to be
Although __DO_VOID is chosen, __DO generates errors. This behavior is described in manual:
... the unused expression (exp1 or exp2 depending on the value of const_exp) may still generate syntax errors. This may change in future revisions.
Working solution
The trick is to substitute the original void expr with some non-void value to be able to compile the __DO case (which is anyway a dead code when expr is void).
#define __expr_or_zero(expr) __builtin_choose_expr(__type_is_void(expr), 0, (expr))
#define DO(expr) \
__builtin_choose_expr(__type_is_void(expr), \
__DO_VOID(expr), \
__DO(__expr_or_zero(expr))) # works fine!
That's it! Here is the complete source code on Ideone: http://ideone.com/EFy4pE
can you accept an answer of "this isn't really possible" ?
not the part about returning from a macro. but the part about conditionally testing expr for its return type.
in effect, you're asking for something like the following:
let's say instead of some magical check called "is_expr_type_void(expr)", you instead simply pass a 1 or a 0 at the time of the call to indicate is_void or !is_void in the following variation of your macro:
#define TIMER(is_void, expr, fmt_msg, ...) \
({ \
struct timeval before, after; \
uint64_t time_span; \
int time_span_sec, time_span_usec; \
gettimeofday(&before, NULL); \
if (is_void) \
(expr) \
else \
typeof(expr) _timer_expr__ = (expr); \ // <- static if?
gettimeofday(&after, NULL); \
time_span = (after.tv_sec * 1000000 + after.tv_usec) \
- (before.tv_sec * 1000000 + before.tv_usec); \
time_span_sec = time_span / 1000000; \
time_span_usec = time_span % 1000000; \
TRACE(fmt_msg "\n%s : %d.%d seconds", \
#expr, time_span_sec, time_span_usec, ...); \
if (!is_void) \
_timer_expr__; \
})
this simply cannot work. the preprocessor would create code for that if-else conditional in all cases, both void and non-void function calls. and both sides would compile fine for non-void functions. but the compiler would always choke on the "else" part of the conditional when TIMER is invoked with a void function … despite the fact that the code would never be called.
(now if there existed a really smart compiler that could both identify that it would be dead code and dead-strip it prior to flagging it as a compile time error, you'd be in luck! but i don't think gcc 4.6 is that smart … )
this leaves you with what would be a preferred option of a #if (is_void) conditional inside the #define. but that's simply not allowed. since, as this answer points out in attempting to answer a similar question about conditional preprocessing, the preprocessor is not turing-complete.
so … despite your desire to have a single macro, i think your simplest answer is to create one for void functions, and one for functions with return values.
As long as you've got typeof and _Generic, you can do also do it without __builtin_types_compatible_p or __builtin_choose_expr.
The caveat is that _Generic won't let you match void so instead of matching Expr against void, match (typeof(Expr)*){0} against void*.
Below is eldar-abusalimov example modified to use _Generic instead of __builtin_types_compatible_p and __builtin_choose_expr:
#include <stdio.h>
#define __type_is_void(expr) _Generic((typeof(expr)*){0}, void*:1, default:0)
#define __expr_or_zero(expr) _Generic((typeof(expr)*){0}, void*:0, default:(expr))
#define DO(expr) \
_Generic((typeof(expr)*){0}, \
void*:__DO_VOID(expr), \
default:__DO(__expr_or_zero(expr)))
#define __DO(expr) \
({ typeof(expr) __ret; puts("do nonvoid"); __ret = (expr); __ret; })
#define __DO_VOID(expr) \
(void)({ puts("do void"); (void)(expr); })
void foo(void) { }
int bar(void) { return 1; }
int main(void)
{
DO(foo());
DO(bar());
return 0;
}
If you really need to return from macro, use inline function instead.

How to implement a generic macro in C?

FUNC(param);
When param is char *,dispatch to func_string.
when it's int,dispatch to func_int
I think there may be a solution to this,as variable types are known at compile time..
This will be possible with C1X but not in the current standard.
It will look like this:
#define cbrt(X) _Generic((X), long double: cbrtl, \
default: cbrt, \
float: cbrtf)(X)
Variable types are known to the compiler, but not to the preprocessor (which sees the code simply as unstructured text a stream of tokens, and performs only simple replacement operations on it). So I am afraid you can't achieve this with C macros.
In C++, they invented templates to solve such problems (and more).
You can test for the characteristics of the types.
For example, int can hold a negative value, while char* can't. So if ((typeof(param))-1) < 0, param is unsigned:
if (((typeof(param))-1) < 0) {
do_something_with_int();
} else {
do_something_with_char_p();
}
The compiler obviously optimizes this out.
Try it here: http://ideone.com/et0v1
This would be even easier if the types had different sizes. For example, if you want to write a generic macro than can handle different character sizes:
if (sizeof(param) == sizeof(char)) {
/* ... */
} else if (sizeof(param) == sizeof(char16_t)) {
/* ... */
} else if (sizeof(param) == sizeof(char32_t)) {
/* ... */
} else {
assert("incompatible type" && 0);
}
GCC has a __builtin_types_compatible_p() builtin function that can check for types compatibility:
if (__builtin_types_compatible_p(typeof(param), int)) {
func_int(param);
} else if (__builtin_types_compatible_p(typeof(param), char*)) {
func_string(param);
}
Try it here: http://ideone.com/lEmYE
You can put this in a macro to achieve what you are trying to do:
#define FUNC(param) ({ \
if (__builtin_types_compatible_p(typeof(param), int)) { \
func_int(param); \
} else if (__builtin_types_compatible_p(typeof(param), char*)) { \
func_string(param); \
} \
})
(The ({...}) is a GCC's statement expression, it allows a group of statements to be a rvalue.
The __builtin_choose_expr() builtin can choose the expression to compile. With __builtin_types_compatible_p this allows to trigger an error at compile-time if the type of param is not compatible with both int and char*: (by compiling somehting invalid in this case)
#define FUNC(param) \
__builtin_choose_expr(__builtin_types_compatible_p(typeof(param), int) \
, func_int(param) \
, __builtin_choose_expr(__builtin_types_compatible_p(typeof(param), char*) \
, func_string(param) \
, /* The void expression results in a compile-time error \
when assigning the result to something. */ \
((void)0) \
) \
)
This is actually a slightly modified example from __builtin_choose_expr docs.
There is no possibility to run time check types in C89 / ANSI C, but there is an extension to gcc which allows it. typeof or something along those lines if I remember. I saw it in the Linux Kernel once.
In kernel.h:
#define min(x, y) ({ \
typeof(x) _min1 = (x); \
typeof(y) _min2 = (y); \
(void) (&_min1 == &_min2); \
_min1 < _min2 ? _min1 : _min2; })
Take a look at this article: GCC hacks in the Linux kernel
When I first saw this I actually asked a question here on SO about:
min macro in kernel.h
I'm not quite sure exactly how you would use it to solve your problem, but it's something worth taking a look at.
You can't do this with a macro. Macro's value are substituted at compile time and are not intepreted. They are just substitutions.
Variable types are indeed known at compile time, however macro expansion takes place before compilation. I suggest you implement 2 overloaded functions instead of a macro.
my definition of a generic:
a structured abstract type which can only be fully defined with an input of other concrete types
this sounds exactly like a macro to me
pardon the psudo c code, my c is rusty
#include <stdio.h>
// todo: ret=self needs vec3##generic_t##_copy(self, ret);
// not to mention we should probably be using __builtin_add_overflow
// __builtin_add_overflow might actually itself be a reasonably generics method example
// please bear with me
#define GENERIC_VEC3_ADD(generic_t) \
generic_t vec3##generic_t##_add(generic_t self, generic_t other) {\
generic_t ret = self;\
ret[0] += other [0];;\
ret[1] += other [1];\
ret[2] += other [2];\
return ret;\
}
#define GENERIC_VEC3_FREPR(generic_t, printf_ts) \
int vec3##generic_t##_frepr(generic_t self, FILE fd)\
rerurn fprintf(fd, "<vec3##generic_t (##printf_ts##, printf_ts##, printf_ts##)>", \
self[0], self[1], self[2]);\
}
// here is the generic typedef, with some methods
#define GENERIC_VEC3(genetic_t, printf_ts) \
typedef vec3##generic_t generic_t[3];\
GENERIC_VEC3_ADD(generic_t) \
GENERIC_VEC3_FREPR(generic_t, printf_ts)
// later we decide what types we want this genic for
GENERIC_VEC3(int, %ul)
// and use our generic
int main()
{
vec3int foo = { 1, 2, 3 };;
vec3int bar = { 1, 2, 3 };;
vec3int sum = vec3int_add(foo, bar);
vec3int_frepr(sum, stderr);
fprintf(stderr, "\n");
exit EXIT_SUCCESS;
}

Resources