This multi line macro from the Nilorea library fails to compile when I include it in my C++ project. It is marked as extern "C".
Tried GodBolt, and the GCC 8.1 compiler barfs on the if statement in the following code : https://godbolt.org/z/Lq_7aT
#define Free( __ptr )\
if ( __ptr )\
{\
free( __ptr );\
__ptr = NULL;\
}
int* i = 0;
Free(i);
It should compile. Is this a matter of the standard in use?
I edited the question with a bad compilable example.
The Godbolt code fails to compile because
You are calling the code outside a function
You are attempting to assign to literal 0
You fail to include the necessary headers.
In addition, as noted in the comments, double underscore in identifiers is reserved for the implementation. The compiler doesn’t diagnose this but it’s illegal anyway.
When fixing these three issues, it works:
#include <stdlib.h>
#define Free(ptr) \
if (ptr) \
{ \
free(ptr); \
ptr = NULL; \
}
int main(void) {
int *px = NULL;
Free(px);
}
(I’ve also fixed the atrocious, inconsistent spacing.)
Related
I have a combination of libraries that are suffering from namespace pollution due to the use of macros and macro names in function prototypes of the same name. Specifically, I am using my GUI library Eagle and my friend's networking library Nilorea.
How do I obtain a list of all the function like macros included in my code? I looked at MSVS and CodeBlocks and I can't seem to find a way to list them. I can also use grep, but that is only effective on a directory or easily obtained list of files.
I read about this (Macro and function with same name) and discovered I can (surround) a function name in a declaration to prevent macro expansion, but that only solves the instances where I am using a function with the same name as the macro. MinGW is using macro names for functions I cannot change.
I avoided some namespace collision by separating out bad headers like windows.h and defining NOGDI to avoid some others, but I can't seem to get rid of them all.
I know I can #undef a symbol if I need to and I've had limited success with this, along with changing the order of inclusion of headers, but I'm still having problems.
So what options do I have to scrub my code of these obnoxious macros?'
I looked at the CPP (C preprocessor) program's help and it doesn't show any abilities to list the macros in a given header.
Do I need to write my own custom solution? What about Clang?
For an example of the collision between Nilorea and MinGW-W64 see here :
This is a macro in Nilorea that collides with mingw :
/*! Free Handler to get errors */
#define Free( ptr ) \
if ( ptr )\
{\
free( ptr );\
ptr = NULL;\
}\
else\
{\
n_log( LOG_DEBUG , "Free( %s ) already done or NULL at line %d of %s \n", #ptr , __LINE__ , __FILE__ );\
}
The compiler error it generates is misleading, but points to c:\mingw\i686-w64-mingw32\include\objidbase.h and oaidl.h in these function prototypes :
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("00000002-0000-0000-c000-000000000046")
IMalloc : public IUnknown
{
virtual void * STDMETHODCALLTYPE Alloc(
SIZE_T cb) = 0;
virtual void * STDMETHODCALLTYPE Realloc(
void *pv,
SIZE_T cb) = 0;
virtual void STDMETHODCALLTYPE Free(
void *pv) = 0;
virtual SIZE_T STDMETHODCALLTYPE GetSize(
void *pv) = 0;
virtual int STDMETHODCALLTYPE DidAlloc(
void *pv) = 0;
virtual void STDMETHODCALLTYPE HeapMinimize(
) = 0;
};
Given the following code in a project I'm working on:
/* Pre-definitions in a pre-definitions file to be included in the project */
#ifdef WIN32
#define __FUNCNAME__ __FUNCTION__
#else
#define __FUNCNAME__ __func__
#endif
/* My definitions */
#define MAC() \
MAC1()
#define MAC1() \
myPrintFunction(__FUNCNAME__)
/* My print function */
void myPrintFunction(const char * functionName)
{
printf("\n func name: %s \n",functionName);
}
/* Macro usage example function */
void myFunction()
{
if (some_condition)
{
MAC();
}
}
The function name is presented as an empty string.
Any idea why, and how can I fix it?
Code compiled and tested on Linux machine, using GCC compiler.
Use __func__ out of the box. It's been part of the C standard since C99. Change your compiler settings to use at least that standard.
Note that __func__ is not a macro but a predefined identifier which takes the form such that writing it anywhere within a function body is exactly equivalent to using it at that point, having first written
static const char __func__[] = "function-name";
just after the opening brace of a function body.
Formally the behaviour of your current code is undefined. Any symbol containing two consecutive underscores is reserved by the system. (That includes macro names, function names, and variable names.)
Your code as presented gives the expected result (once I'd added the necessary includes and main):
#include <stdio.h>
#ifdef WIN32
#define __FUNCNAME__ __FUNCTION__
#else
#define __FUNCNAME__ __func__
#endif
/* My definitions */
#define MAC() \
MAC1()
#define MAC1() \
myPrintFunction(__FUNCNAME__)
void myPrintFunction(const char * functionName)
{
printf("\n func name: %s \n",functionName);
}
int main()
{
MAC();
}
I compiled this using gcc -std=c11 -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds with no warnings.
You should really post a complete (but minimal) example that actually compiles, along with the compiler flags you used, as something must certainly be different to explain the symptoms you describe.
Also, when writing statements as macros, you may find it helpful to use the do {...} while (0) idiom to avoid unexpected expansions changing the control flow.
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;
}
We have a function macro #define FOO(arg) foo(arg) with int foo(const char* bar);. When NDEBUG is defined FOO is defined as #define FOO(arg) 0, however this causes many compiler warnings because in many cases FOO's return value is not used. The solution should work with with ANSI C compilers and cause no warnings. I've tried:
(void)0: can't be assigend to variable
static int foo(const char* bar) { return 0; } : causes unused static function warning in some modules
static inline int foo(const char* bar) { return 0; } : only works with C99 compilers
Thanks for your help!
edit1:
It's somewhat like a trace macro and used all over the project. Mostly it's just used as a statement like FOO("function x called");, but in a few cases I saw if (FOO("condition a")) { /* some more debug output */ }. With NDEBUG defined and optimization enabled nothing should be left of FOO. I didn't come up with this, but I have to clean up this mess :).
edit2: I should add that for gcc release builds these flags are used: -O3 -Wall -ansi
edit3: For now I'm going with __inline int dummy() { return 0; }. __inline works with both VisualC and GCC in ansi mode.
I guess it's a little bit compiler dependent but this should work:
#ifndef NDEBUG
#define FOO(arg) foo(arg)
#else
#define FOO(arg) ((int)0)
#endif
It prevents the "expression has no effect" warning, it does nothing and its value when used is still 0.
EDITED
It seems it's something not so portable so (now) you have these conditions:
(0) or ((int)0) work at least on VC 2010.
__noop should work on any version of VC after 2003.
VC6 is not a problem because it doesn't emit the C4555 warning at all. For other compilers you may use:
((void)0, 0) It may work on a lot of compilers (maybe it's the more portable one?).
inline int foo(const char* bar) { return 0; } works with any other C99 compiler (as you wrote you may need to declare it as static on gcc).
For any other prehistoric C compiler use the solution pointed by #Jobs: abs(0)
What you could do to prevent the warning is the following:
#ifndef NDEBUG
#define FOO(arg) foo(arg)
#else
#define FOO(arg) abs(0)
#endif
I'm not saying this is ideal (you'd have to make sure stdlib.h is included everywhere, for example) but it does prevent the warning.
I'd do something that is dependent on the C version. In the header file:
#if __STDC_VERSION__ > 199900L
inline int foo(const char* bar) { return 0; }
#else
int foo(const char* bar);
#endif
in one compilation unit
#if __STDC_VERSION__ < 199900L
int foo(const char* bar) { return 0; }
#else
int foo(const char* bar);
#endif
or use for the oldish C version something like Job's answer, that is a function that is certain to be optimized out but that doesn't produce the warning.
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;
}