I am trying to generate overloaded functions using _Generic macro in C11, and I have stopped on zero arguments function support, e.g:
#define msg(_1) _Generic((_1), char*: msg_string, default: msg_none)(_1)
char* msg_none(void){
return moo_string("Have a nice day!");
}
char* msg_string(char* message){
int msglen = strlen(message);
char* result = malloc(msglen + 3);
sprintf(result, "<%s>\n", message);
return result;
}
For now compiling and running:
printf("%s",msg("hello!"));
goes without any problem, but:
printf("%s",msg());
throws error:
main.c:7:17: error: expected expression
printf("%s",msg());
I am using:
clang --version
clang version 3.5.0 (tags/RELEASE_350/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
GCC throws:
main.c:7:5: warning: implicit declaration of function ‘_Generic’
so I understand _Generic is not supported this version of gcc:
gcc --version
gcc (Gentoo 4.8.3 p1.1, pie-0.5.9) 4.8.3
Is my problem even solvable or I just overestimate capabilities of _Generic, or I just need to upgrade my compilers to use this options properly ?
C has variadic macros that may receive zero or more arguments
#define msg(...) _Generic((__VA_ARGS__+0), char*: msg_string, default: msg_none)(__VA_ARGS__)
here the +0 in addition ensures that an array to pointer conversion is performed for your string argument, which you seem to assume.
The later is important since gcc and clang currently differ in their behavior if the selection expression is an array.
Edit: You probably also would want your macro to work if someone passes in a char const* so you should add that case, too.
Your problem is not directly related to _Generics. You simply defined you macro #define msg(_1) with an argument, therefore you have to pass an argument.
If you don't rely on compiler extensions you cannot pass zero or more arguments to a _Generic macro. You will have to choose between zero or one arguments as shown here or, 1 or more.
This is my solution for any macro combination, but it involves a dummy argument. You can define you own type that will serve as an indicator of an emtpy macro
typedef struct
{
int unused ;
} emtpy ;
const empty msg_empty = { 0 } ;
char* msg_none(empty e)
{
( void )e ;
return moo_string("Have a nice day!");
}
#define msg(_1) _Generic((_1), char*: msg_string, empty : msg_none)(_1)
And then call it with:
msg( msg_empty ) ;
Which will call the msg_none function.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define dummy void
#define ARGS_AUX(_0, VAR, ...) VAR
#define ARGS(...) ARGS_AUX(dummy, ##__VA_ARGS__, NULL) //gnu extensions
#define MSG(var) (_Generic(var, char*: msg_string(var), default: msg_none()))
#define msg(...) MSG(ARGS(__VA_ARGS__)) //MSG(NULL) when no argument
char *moo_string(const char *s){
return (char*)s;
}
char* msg_none(void){
return moo_string("Have a nice day!");
}
char* msg_string(char* message){
int msglen = strlen(message);
char* result = malloc(msglen + 4);
sprintf(result, "<%s>\n", message);
return result;
}
int main(void){
printf("%s\n", msg());//Have a nice day!
printf("%s\n", msg((char*)"hello!"));//<hello!>, type is char[7] when no cast
return 0;
}
Related
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
-----------------------------
In this example code a macro is either defined or commented out by the programmer in order to remove a function from the released software.
#include <stdio.h>
#define MACRO //or omitted
#ifdef MACRO
void Function(const char* str)
{
printf("%s\n", str);
}
#else
#define Function(str)
#endif
int main(void)
{
Function("hello world");
getchar();
return 0;
}
Is there anything wrong with this?
Even though your solution works, I prefer the following approach:
#include <stdio.h>
#define MACRO //or omitted
#ifdef MACRO
#define FUNCTION(a) Function(a);
#else
#define FUNCTION(a)
#endif
#ifdef MACRO
void Function(const char* str)
{
printf("%s\n", str);
}
#endif
int main(void)
{
FUNCTION("hello world")
getchar();
return 0;
}
Note: FUNCTION is the macro, Function is the actual name of the function
This works by defining the macro FUNCTION(a) to a call to Function(const char*) when MACRO is enabled. On the other hand, when MACRO is disabled, calls to FUNCTION(a) will be defined to nothing.
I tend to prefer this method since it would be easier to abstract away the macro used to define your call from the macro defining your function definition. You might have cases where in release mode you only need to remove some of the calls to Function. In that case the definition of Function() is still required. For example:
#include <stdio.h>
#define DEBUG //or omitted
#ifdef DEBUG
#define FUNCTION(a) Function(a);
#else
#define FUNCTION(a)
#endif
void Function(const char* str)
{
printf("%s\n", str);
}
int main(void)
{
// Call function with Hello World only in debug
FUNCTION("hello world")
getchar();
// Call function with goodbye world in both debug and release
Function("goodbye world");
return 0;
}
It will work. But the entire symbol is removed this way. I prefer the following method.
#include <stdio.h>
#define MACRO 1
#if MACRO
void Function(const char* str)
{
printf("%s\n", str);
}
#else
void Function(const char *str){}
#endif
int main(void)
{
Function("hello world");
getchar();
return 0;
}
The following has changed:
The #if now compares a boolean. Your IDE is now able to find where MACRO is defined, in all cases. (right click, find definition)
You can, by changing MACRO to 2, change the entire meaning of Function. For example, a release compiled variant might contain a print to file or system log.
There will always be a symbol for Function, even if it does nothing, even in compiled code. This has the benefit that the string literals in the argument still count to the size statistics. As an embedded developer, I find this important.
Obviously, this is partly the preference of the one who crafts the code.
I am trying to use dlopen() and dlsym() in my code and compile it with gcc.
Here is the first file.
/* main.c */
#include <dlfcn.h>
int main()
{
void *handle = dlopen("./foo.so", RTLD_NOW);
if (handle) {
void (*func)() = dlsym(handle, "func");
func();
}
return 0;
}
Here is the second file.
/* foo.c */
#include <stdio.h>
void func()
{
printf("hello, world\n");
}
Here is how I compile and run the code.
$ gcc -std=c99 -pedantic -Wall -Wextra -shared -fPIC -o foo.so foo.c
$ gcc -std=c99 -pedantic -Wall -Wextra -ldl -o main main.c
main.c: In function ‘main’:
main.c:10:26: warning: ISO C forbids initialization between function pointer and ‘void *’ [-Wpedantic]
void (*func)() = dlsym(handle, "func");
^
$ ./main
hello, world
How can I get rid of the warning?
Type casting doesn't help. If I try to type cast the return value of dlsym() into a function pointer, I get this warning instead.
main.c:10:26: warning: ISO C forbids conversion of object pointer to function pointer type [-Wpedantic]
void (*func)() = (void (*)()) dlsym(handle, "func");
^
What would convince the compiler that this code is fine?
If you want to be pedantically correct, don't try to resolve the address of a function. Instead, export some kind of structure from the dynamic library:
In the library
struct export_vtable {
void (*helloworld)(void);
};
struct export_vtable exports = { func };
In the caller
struct export_vtable {
void (*helloworld)(void);
};
int main() {
struct export_vtable* imports;
void *handle = dlopen("./foo.so", RTLD_NOW);
if (handle) {
imports = dlsym(handle, "exports");
if (imports) imports->helloworld();
}
return 0;
}
This technique is actually quite common, not for portability -- POSIX guarantees that function pointers can be converted to and from void* -- but because it allows more flexibility.
This made my code sufficiently pedantic:
*(void**)(&func_ptr) = dlsym(handle, "function_name");
(I found it here http://pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html)
The problem here is that a pointer to object is subtly separated from a function pointer. In ISO/IEC 9899:201x paper §6.3.2.3 Pointers it's stated:
A pointer to void may be converted to or from a pointer to any
object type. A pointer to any object type may be converted to a
pointer to void and back again; the result shall compare equal to
the original pointer.
.
A pointer to a function of one type may be converted to a pointer to
a function of another type and back again; the result shall compare
equal to the original pointer. If a converted pointer is used to
call a function whose type is not compatible with the pointed-to
type, the behavior is undefined.
So a function pointer is different from object pointers, and consequently the assignment of a void * to a function pointer is always non strictly compliant.
Anyway, as I said in comments, in 99.9999....9999% of cases it is permitted thanks to the ANNEX J - Portability issues, §J.5.7 Function pointer casts of the previously mentioned paper that states:
A pointer to an object or to void may be cast to a pointer to a
function, allowing data to be invoked as a function (6.5.4).
A pointer to a function may be cast to a pointer to an object or to
void, allowing a function to be inspected or modified (for example,
by a debugger) (6.5.4).
Now on the practical side a technique that avoid the splitting of code in more files is to use pragmas to suppress pedantic warnings for a small piece of code.
The more brutal form can be:
/* main.c */
#include <dlfcn.h>
#pragma GCC diagnostic push //Save actual diagnostics state
#pragma GCC diagnostic ignored "-pedantic" //Disable pedantic
int main()
{
void *handle = dlopen("./foo.so", RTLD_NOW);
if (handle) {
void (*func)() = dlsym(handle, "func");
func();
}
return 0;
}
#pragma GCC diagnostic pop //Restore diagnostics state
A more sophisticated way could be actuated isolating the offending code in a small function, then forcing its inlining. It's more a makeup than effective solution, but will suppress the unwanted diagnostic:
/* main.c */
#include <dlfcn.h>
#pragma GCC diagnostic push //Save actual diagnostics state
#pragma GCC diagnostic ignored "-pedantic" //Disable pedantic
void (*)() __attribute__((always_inline)) Assigndlsym(void *handle, char *func)
{
return dlsym(handle, func); //The non compliant assignment is done here
}
#pragma GCC diagnostic pop //Restore diagnostics state
int main()
{
void *handle = dlopen("./foo.so", RTLD_NOW);
if (handle) {
void (*func)() = Assigndlsym(handle, "func"); //Now the assignment is compliant
func();
}
return 0;
}
To keep the -pedantic option for your code while having parts of code that are not strictly conforming, separate that code into a separate file with custom warning options.
So, make a function that wraps the dlsym function and returns a function pointer. Put it in a separate file and compile that file without -pedantic.
you can use union, like this:
union {
void *ptr;
void (*init_google_logging) (char* argv0);
} orig_func;
orig_func.ptr = dlsym (RTLD_NEXT, "_ZN6google17InitGoogleLoggingEPKc");
orig_func.init_google_logging (argv0);
The POSIX Standard explicitly states that you can “run” an address passed as a pointer to object (emphasis mine):
Note that conversion from a void * pointer to a function pointer as in:
fptr = (int (*)(int))dlsym(handle, "my_function");
is not defined by the ISO C standard. This standard requires this conversion to work correctly on conforming implementations.
To do that you need to “animate” the object pointer first.
#define ANIMATED_POINTER(FUNC_TYPE, OBJECT_POINTER) \
(*((FUNC_TYPE *)(&(OBJECT_POINTER))))
You can then then invoke the object variable directly,
#include <dlfcn.h>
#define ANIMATED_POINTER(FUNC_TYPE, OBJECT_POINTER) \
(*((FUNC_TYPE *)(&(OBJECT_POINTER))))
typedef void (* MyFuncType) ();
int main () {
void * handle = dlopen("./foo.so", RTLD_NOW);
if (handle) {
void * func_obj_ptr = dlsym(handle, "func");
ANIMATED_POINTER(MyFuncType, func_obj_ptr)();
}
return 0;
}
or you can convert it into another variable of appropriate function type.
#include <dlfcn.h>
#define ANIMATED_POINTER(FUNC_TYPE, OBJECT_POINTER) \
(*((FUNC_TYPE *)(&(OBJECT_POINTER))))
typedef void (* MyFuncType) ();
int main () {
void * handle = dlopen("./foo.so", RTLD_NOW);
if (handle) {
void * func_obj_ptr = dlsym(handle, "func");
MyFuncType func = ANIMATED_POINTER(MyFuncType, func_obj_ptr);
func();
}
return 0;
}
Addition
Although the conversion from an object pointer to a function pointer can be problematic, in every standard C allows to convert different types of function pointers between them. You can exploit this permission and use void (*) (void) as a fixed destination type for your macro.
#define UNTYPED_ANIMATED_POINTER(OBJECT_POINTER) \
(*((void (**) (void))(&(OBJECT_POINTER))))
Hence, imagining an addition.c library containing only,
int add_numbers (int first, int second) {
return first + second;
}
below are four variations of the same code.
#1
#include <dlfcn.h>
#include <stdio.h>
#define UNTYPED_ANIMATED_POINTER(OBJECT_POINTER) \
(*((void (**) (void))(&(OBJECT_POINTER))))
int main () {
void * handle = dlopen("./addition.so", RTLD_NOW);
if (handle) {
int (* add_numbers) (int, int);
void * func_obj_ptr = dlsym(handle, "add_numbers");
add_numbers = (int (*) (int, int)) UNTYPED_ANIMATED_POINTER(func_obj_ptr);
int result = add_numbers(19, 23);
printf("The result is: %d\n", result); // "The result is: 42"
}
return 0;
}
#2
#include <dlfcn.h>
#include <stdio.h>
#define UNTYPED_ANIMATED_POINTER(OBJECT_POINTER) \
(*((void (**) (void))(&(OBJECT_POINTER))))
int main () {
void * handle = dlopen("./addition.so", RTLD_NOW);
if (handle) {
void * func_obj_ptr = dlsym(handle, "add_numbers");
int result = ((int (*) (int, int)) UNTYPED_ANIMATED_POINTER(func_obj_ptr))(19, 23);
printf("The result is: %d\n", result); // "The result is: 42"
}
return 0;
}
#3
#include <dlfcn.h>
#include <stdio.h>
#define UNTYPED_ANIMATED_POINTER(OBJECT_POINTER) \
(*((void (**) (void))(&(OBJECT_POINTER))))
typedef int (* AdditionFunc) (int, int);
int main () {
void * handle = dlopen("./addition.so", RTLD_NOW);
if (handle) {
void * func_obj_ptr = dlsym(handle, "add_numbers");
AdditionFunc add_numbers = (AdditionFunc) UNTYPED_ANIMATED_POINTER(func_obj_ptr);
int result = add_numbers(19, 23);
printf("The result is: %d\n", result); // "The result is: 42"
}
return 0;
}
#4
#include <dlfcn.h>
#include <stdio.h>
#define UNTYPED_ANIMATED_POINTER(OBJECT_POINTER) \
(*((void (**) (void))(&(OBJECT_POINTER))))
typedef int (* AdditionFunc) (int, int);
int main () {
void * handle = dlopen("./addition.so", RTLD_NOW);
if (handle) {
void * func_obj_ptr = dlsym(handle, "add_numbers");
int result = ((AdditionFunc) UNTYPED_ANIMATED_POINTER(func_obj_ptr))(19, 23);
printf("The result is: %d\n", result); // "The result is: 42"
}
return 0;
}
The compiler only "tries to help", so you have to use two typecasts:
#include <stdint.h>
void (*func)() = (void (*)())(intptr_t)dlsym(handle, "func");
I was experimenting with "hacking" the type-system, by not restricting the function pointer argument to accept a function with a specific type of arguments. However, I still wanted to make it type-safe, so I thought I will combine this "hack" with the possibilities of the _Generic keyword.
I have the following four functions:
#include <stdio.h> /* printf() */
#include <stdlib.h> /* EXIT_SUCCESS */
static void
function_i(int *i)
{
printf("%d\n", *i);
}
static void
function_f(float *f)
{
printf("%.2ff\n", *f);
}
static void
caller(void(*func)(),
void *arg)
{
func(arg);
}
static void
except(void(*func)(),
void *arg)
{
printf("unsupported type\n");
}
The first and second will be passed to the third, and I want to make sure, if the type of the function and the argument passed to the third is not right, then the fourth function will be called. Therefore I created the following _Generic selector:
#define handler(func, arg) _Generic((func), \
void(*)(int*): _Generic((arg), \
int* : caller, \
default : except), \
void(*)(float*): _Generic((arg), \
float* : caller, \
default : except), \
default: except)(func, arg)
And then I called them:
int main(void)
{
int i = 12;
float f = 3.14f;
void(*func_ptr_i)(int*) = function_i;
void(*func_ptr_f)(float*) = function_f;
handler(function_i, &i);
handler(function_f, &f);
handler(func_ptr_i, &i);
handler(func_ptr_f, &f);
return EXIT_SUCCESS;
}
The output is very interesting:
unsupported type
unsupported type
12
3.14f
I expected this to work for the first two cases as well, without the need to create a specific function pointer variable for the passed functions. The question is: is this an implementation error in clang's _Generic, or this is the expected behavior? Is so, I'm very curious about why exactly? And how to make it work without creating extra function pointers?
Thanks in advance!
SYS-INFO:
compiler: Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
flags: cc -std=c11 -Wall -v -g
The problem that you are facing is that the choice expression of _Generic is not evaluated. If it would be, your function names would decay to function pointers and everything would work.
Adding a & to your choice expression should fix that.
I'm looking for a creative solution for making sure that variables delivered to a specific macro are declared with type volatile in C language, with TMS470 compiler. meaning:
good method:
volatile int *_p_reg;
VOLATILE_MACRO(_p_reg);
compilation failure:
int *_p_reg;
VOLATILE_MACRO(_p_reg);
I wish to perform the verification after the compilation, meaning going over the disassembly or the debug information and identify those calls.
I can't seem to find any evidence for the volatile in the debug info.
any ideas?
thanks!
I wouldn't expect there to be any, but of course it's totally up to the compiler.
You could of course re-architect it so that the macro does the whole definition, i.e.
#define VOLATILE_MACRO(t, p) volatile t p
and use it like:
VOLATILE_MACRO(int, _p_reg);
but of course that might not work for you.
Two possible solutions using gcc extensions. The run-time version uses __builtin_types_compatible_p and an assert. The compile-time version is similar but uses a hack to get a static assert which fires at compile-time (albeit with a rather cryptic error message):
Run-time
#include <stdio.h>
#include <assert.h>
#define VOLATILE_MACRO(p) \
assert (__builtin_types_compatible_p(typeof(p), typeof(volatile int *)))
int main()
{
volatile int * x;
int * y;
VOLATILE_MACRO(x); // <<< OK
VOLATILE_MACRO(y); // <<< run-time error
return 0;
}
Compile-time
#include <stdio.h>
#include <assert.h>
#define A BUILD_NAME(__LINE__)
#define BUILD_NAME(line) BUILD_NAME2(line)
#define BUILD_NAME2(line) assert_ ## line
#define STATIC_ASSERT(test) typedef char A[(test) ? 1 : -1]
#define VOLATILE_MACRO(p) \
STATIC_ASSERT (__builtin_types_compatible_p(typeof(p), typeof(volatile int *)))
int main()
{
volatile int * x;
int * y;
VOLATILE_MACRO(x); // <<< OK
VOLATILE_MACRO(y); // <<< compile error
return 0;
}
Note that if you need to support other volatile types then the macro can simply be extended with multiple chained __builtin_types_compatible_p tests, e.g.
#define VOLATILE_MACRO(p) \
assert (__builtin_types_compatible_p(typeof(p), typeof(volatile int *)) ||
__builtin_types_compatible_p(typeof(p), typeof(volatile short *)))