Check at runtime if macro was defined - c

During the developing of static library I met the necessity to test the library functions.
The functions checks are not the problem. The main problem is to test every macro definition that the library provides.
I've started with the code like
/* For non-vital macro (OS/WORDSIZE detections) */
# if defined(BXI_ARCH_X32)
printf(" defined : BXI_ARCH_X32\n");
# endif
# if defined(BXI_ARCH_X64)
printf(" defined : BXI_ARCH_X64\n");
# endif
<...>
/* For vital macro */
#if defined(BXI_OS)
printf(" defined : BXI_OS : \"%s\"\n", BXI_OS);
#else
print_failed();
#endif
#if defined(BXI_BITS)
printf(" defined : BXI_BITS: %d\n", BXI_BITS);
#else
print_failed();
#endif
#if defined(BXI_ARCH)
printf(" defined : BXI_ARCH: \"%s\"\n", BXI_ARCH);
#else
print_failed();
#endif
That was cool, but very time-consuming. I wanted a tool that will generate the code for me, or some trick that will allow me to autogenerate the tests via macro like this
TEST_MACRO(BXI_OS)
But, as you know, macro definitions can't generate #if/#else/#endif directives.
I needed a solution that will not only check if the macro defined at runtime, but also print its value to output.

I've met a simillar problem and found another nice trick to implement your TEST_BXI_MACRO_EXISTS with no string.h and extra function calls:
#define STRINGIZE_I(x) #x
#define TEST_BXI_MACRO_EXISTS(name) (#name [0] != STRINGIZE_I(name) [0])
This trick uses the same assumption that stringized value of defined macro does not match stringized name of that macro. But for my case I only needed to check if macro is defined as a numeric constant, string literal or empty value. No function-like macros and other stuff.
This is how it works:
#define MACRO "Content"
TEST_BXI_MACRO_EXISTS(MACRO)
// translates to ("MACRO"[0] != "\"Content\""[0])
// first letter of a valid macro name can never be equal to '"'
#define MACRO 3.14
TEST_BXI_MACRO_EXISTS(MACRO)
// translates to ("MACRO"[0] != "3.14"[0])
// first letter of a valid macro name can never be equal to a digit
#define MACRO
TEST_BXI_MACRO_EXISTS(MACRO)
// translates to ("MACRO"[0] != ""[0])
// first letter of a valid macro name can never be equal to a '\0'
This approach can also be easily used to test whether macro defines a numeric constant, string literal or empty value like your approach does by checking the value of STRINGIZE_I(name) [0].
So far I have no idea how to test function-like macros this way, but I thought sharing this with others could be useful anyway.

But, as this is Q&A-style article, I've found the solution.
The final result looks as follows:
TEST_BXI_MACRO_STRING(BXI_OS);
TEST_BXI_MACRO_STRING(BXI_ARCH);
TEST_BXI_MACRO_I32 (BXI_BITS);
TEST_BXI_MACRO_EXISTS_WEAK(BXI_ARCH_X32); // _WEAK as we don't need to fail
TEST_BXI_MACRO_EXISTS_WEAK(BXI_ARCH_X64);
The result:
Let us see every one of them closely
TEST_BXI_MACRO_STRING
This one is pretty simple:
#define TEST_BXI_MACRO_STRING(name) \
do \
{ \
print_macro_name(#name); \
if (!TEST_BXI_MACRO_DEFINED(#name, name(1))) \
print_macro_undefined_exit(); \
if (strlen(name "") == 0) \
print_macro_undefined_exit(); \
print_macro_value_string(name ""); \
} \
while (0)
We just using the idea that C allows const strings auto-concatenation. So when the macro exists we will receive
#define MACRO "Content"
"Content" "" = "Content"
and when it doesn't
"" = ""
Then we look at the length of the resulting string, and when it's 0 - bingo, macro is not defined. This will NOT work for "" macro, but this special case could be checked with TEST_BXI_MACRO_EXISTS
TEST_BXI_MACRO_I32
#define TEST_BXI_MACRO_I32(name) \
do \
{ \
print_macro_name(#name); \
if (!TEST_BXI_MACRO_DEFINED(#name, name(1))) \
print_macro_undefined_exit(); \
if ((5 * name + 1) == 5) \
print_macro_undefined_exit(); \
print_macro_value_signed(name + 0); \
} \
while (0)
NOTE: you can similarly create ...MACRO_U32 version just by replacing the printer formatter.
Here we use the fact that '+' operator could be unary AND binary.
Let us simulate three cases:
#define MACRO (10)
In this case the complete formula will look as follows:
5 * 10 + 1 => 50 + 1 => 51
#define MACRO (0)
In this case the multiplication fades out:
5 * 0 + 1 => 0 + 1 => 1
In some cases you can use this for additional check if the defined macro is 0 (like for preprocessing options and stuff)
#define MACRO
This case shows some math magic:
5 * + 1 => 5 * (+1) => 5 * 1 => 5
As +1 is interpreted as simple 1 we receive 5.
TEST_BXI_MACRO_EXISTS
#define TEST_BXI_MACRO_DEFINED_I(strstr, fnc) (strcmp(#fnc, strstr "(1)"))
#define TEST_BXI_MACRO_DEFINED(str, fnc) TEST_BXI_MACRO_DEFINED_I(str, fnc)
#define TEST_BXI_MACRO_EXISTS(name) \
do \
{ \
print_macro_name(#name); \
if (!TEST_BXI_MACRO_DEFINED(#name, name(1))) \
print_macro_undefined_exit(); \
else \
print_macro_defined(); \
} \
while (0)
This implementation uses the fact that the string value of macro should not expand same as its name (as #define A A is useles)
Additional functions
For those who want the printing functions, here they are:
void print_macro_name(const char * name)
{
printf(" checking: %-20s: ", name);
}
void print_macro_undefined_exit(void)
{
printf("\033[1;31mUNDEFINED\033[0m\n");
exit(1);
}
void print_macro_defined(void)
{
printf("\033[1;33mDEFINED\033[0m\n");
}
void print_macro_undefined(void)
{
printf("\033[1;32mUNDEFINED\033[0m\n");
}
void print_macro_value_string(const char * value)
{
printf("\"%s\"\n", value);
}
void print_macro_value_signed(i32 value)
{
printf("%d\n", value);
}
void print_macro_value_unsigned(u32 value)
{
printf("%u\n", value);
}

Related

Default arguments to C macros

Suppose I have function bshow() with signature
void bshow(int arg0, int arg1, int arg2);
but for arbitrary reasons I want to implement it as a macro.
Furthermore, I want the function have default arguments
int arg0=0x10;
int arg1=0x11;
int arg2=0x12;
I've already done this for the case that bshow() is a function, using the standard tricks.
But how can I do it as a macro?
Eg. suppose I have a macro nargs() that uses the C Preprocessor to count the number of arguments. Eg.
nargs() // get replaced by 0 by the preprocessor
nargs(a) // get replaced by 1 by the preprocessor
nargs(a,b) // get replaced by 2 by the preprocessor
I'd like to do something like (which doesn't work):
#define arg0_get(a0,...) a0
#define arg1_get(a0,a1,...) a1
#define arg2_get(a0,a1,a2,...) a2
#define bshow(...) do{ \
int arg0=0x10; if(0<nargs(__VA_ARGS__)) arg0 = arg0_get(__VA_ARGS__); \
int arg1=0x11; if(1<nargs(__VA_ARGS__)) arg1 = arg1_get(__VA_ARGS__); \
int arg2=0x12; if(2<nargs(__VA_ARGS__)) arg2 = arg2_get(__VA_ARGS__); \
/* do stuff here */ \
}while(0)
Actually I've already implemented the bshow() function as a macro, as follows (here it has the actual number of arguments):
#define __bshow(bdim,data, nbits,ncols,base)({ \
bdim,data, nbits,ncols,base; \
putchar(0x0a); \
printf("nbits %d\n",nbits); \
printf("ncols %d\n",ncols); \
printf("base %d\n",base); \
})
#define _bshow(bdim,data, nbits,ncols,base, ...) __bshow(bdim,data, nbits,ncols,base)
#define bshow(...) \
if( 2==nargs(__VA_ARGS__)) _bshow(__VA_ARGS__, 32,24,16,0,__VA_ARGS__); \
else if(3==nargs(__VA_ARGS__)) _bshow(__VA_ARGS__, 24,16,0,__VA_ARGS__); \
else if(4==nargs(__VA_ARGS__)) _bshow(__VA_ARGS__, 16,0,__VA_ARGS__); \
else if(5==nargs(__VA_ARGS__)) _bshow(__VA_ARGS__, 0,__VA_ARGS__); \
// test
bshow(0,1);
bshow(0,1, 10);
bshow(0,1, 10,11);
bshow(0,1, 10,11,12);
EDIT:
The proposed solution doesn't have the intended effect because it seems to "instantiate" all instances of the macro, which in general has unintended consequences.
But I wonder if there's a more elegant way to do it.
It'd also be nice to abstract away the entire construction inside its own macro, so that one can apply it to other functions easily, as opposed to having to write the boilerplate manually for each function/macro.
Also this wasn't too helpful.
I found a nice answer.
What you do is you call the vfn() macro, which is (I think) a higher-order macro that returns a macro that returns the token concatenated with the number of args (in hex base, no 0-padding) and then evaluates it at the args. Or something.
Eg. supposed you want to overload a macro called bshow(). You #define the macro bshow() as #define bshow() vfn(bshow,__VA_ARGS__), and you define 1 instance of bshow for each argument count (eg. #define bshow0(...), for 0 arguments, #define bshow1(...) for 1 argument, #define bshow2(...) for 2 arguments, etc.). So now, eg., bshow(0,1) returns bshow2() (because you called it with 2 arguments) evaluated at (0,1), which is _bshow(0,1, 16,32,16), and then _bshow(0,1, 16,32,16) gets evaluated too. You can check the final preprocessor output by running gcc with the -E option, but the intermediate steps are hard to understand (for me).
You also need to decide on the mandatory args and the optional args.
That's almost all I (sort of) understand about what's going on, although I did upload a YT tutorial a while ago on how the argument-counting works.
// ----------------------------------------------------------------
// library
#define __nargs100__(a00,a01,a02,a03,a04,a05,a06,a07,a08,a09,a0a,a0b,a0c,a0d,a0e,a0f,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a1a,a1b,a1c,a1d,a1e,a1f,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a2a,a2b,a2c,a2d,a2e,a2f,a30,a31,a32,a33,a34,a35,a36,a37,a38,a39,a3a,a3b,a3c,a3d,a3e,a3f,a40,a41,a42,a43,a44,a45,a46,a47,a48,a49,a4a,a4b,a4c,a4d,a4e,a4f,a50,a51,a52,a53,a54,a55,a56,a57,a58,a59,a5a,a5b,a5c,a5d,a5e,a5f,a60,a61,a62,a63,a64,a65,a66,a67,a68,a69,a6a,a6b,a6c,a6d,a6e,a6f,a70,a71,a72,a73,a74,a75,a76,a77,a78,a79,a7a,a7b,a7c,a7d,a7e,a7f,a80,a81,a82,a83,a84,a85,a86,a87,a88,a89,a8a,a8b,a8c,a8d,a8e,a8f,a90,a91,a92,a93,a94,a95,a96,a97,a98,a99,a9a,a9b,a9c,a9d,a9e,a9f,aa0,aa1,aa2,aa3,aa4,aa5,aa6,aa7,aa8,aa9,aaa,aab,aac,aad,aae,aaf,ab0,ab1,ab2,ab3,ab4,ab5,ab6,ab7,ab8,ab9,aba,abb,abc,abd,abe,abf,ac0,ac1,ac2,ac3,ac4,ac5,ac6,ac7,ac8,ac9,aca,acb,acc,acd,ace,acf,ad0,ad1,ad2,ad3,ad4,ad5,ad6,ad7,ad8,ad9,ada,adb,adc,add,ade,adf,ae0,ae1,ae2,ae3,ae4,ae5,ae6,ae7,ae8,ae9,aea,aeb,aec,aed,aee,aef,af0,af1,af2,af3,af4,af5,af6,af7,af8,af9,afa,afb,afc,afd,afe,aff,a100,...) a100
#define __nargs__(...) __nargs100__(,##__VA_ARGS__, ff,fe,fd,fc,fb,fa,f9,f8,f7,f6,f5,f4,f3,f2,f1,f0,ef,ee,ed,ec,eb,ea,e9,e8,e7,e6,e5,e4,e3,e2,e1,e0,df,de,dd,dc,db,da,d9,d8,d7,d6,d5,d4,d3,d2,d1,d0,cf,ce,cd,cc,cb,ca,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0,bf,be,bd,bc,bb,ba,b9,b8,b7,b6,b5,b4,b3,b2,b1,b0,af,ae,ad,ac,ab,aa,a9,a8,a7,a6,a5,a4,a3,a2,a1,a0,9f,9e,9d,9c,9b,9a,99,98,97,96,95,94,93,92,91,90,8f,8e,8d,8c,8b,8a,89,88,87,86,85,84,83,82,81,80,7f,7e,7d,7c,7b,7a,79,78,77,76,75,74,73,72,71,70,6f,6e,6d,6c,6b,6a,69,68,67,66,65,64,63,62,61,60,5f,5e,5d,5c,5b,5a,59,58,57,56,55,54,53,52,51,50,4f,4e,4d,4c,4b,4a,49,48,47,46,45,44,43,42,41,40,3f,3e,3d,3c,3b,3a,39,38,37,36,35,34,33,32,31,30,2f,2e,2d,2c,2b,2a,29,28,27,26,25,24,23,22,21,20,1f,1e,1d,1c,1b,1a,19,18,17,16,15,14,13,12,11,10,f,e,d,c,b,a,9,8,7,6,5,4,3,2,1,0)
#define __vfn(name, n) name##n
#define _vfn( name, n) __vfn(name, n)
#define vfn( fn, ...) _vfn(fn, __nargs__(__VA_ARGS__))(__VA_ARGS__)
// ----------------------------------------------------------------
// example
// backend: actual implementation, 2 mandatory args, 3 optional args
#define _bshow(bdim,data, ncols,nbits,base)({ \
/* do stuff here */ \
})
// "frontend", default arguments get implemented here. the suffix is the number of arguments, in hexadecimal base
#define bshow2(...) _bshow(__VA_ARGS__, 16,32,16)
#define bshow3(...) _bshow(__VA_ARGS__, 32,16)
#define bshow4(...) _bshow(__VA_ARGS__, 16)
#define bshow5(...) _bshow(__VA_ARGS__)
#define bshow(...) vfn(bshow,__VA_ARGS__)
// test
bshow(0x100,data0);
bshow(0x100,data0, 14);
bshow(0x100,data0, 12,16);
bshow(0x100,data0, 10, 8,2);

Verify macro argument size at compilation time

Let's assume I have a macro (more details about why, is below in the P.S. section)
void my_macro_impl(uint32_t arg0, uint32_t arg1, uint32_t arg2);
...
#define MY_MACRO(arg0, arg1, arg2) my_macro_impl((uint32_t)(arg0), (uint32_t)(arg1), (uint32_t)(arg2))
The HW on which this macro is going to be used is little endian and uses 32bit architecture so that all the pointers are up to (and including) 32 bit width. My goal is to warn the user when it passes uint64_t or int64_t parameter by mistake.
I was thinking about using sizeof like this
#define MY_MACRO(arg0, arg1, arg2) do \
{ \
static_assert(sizeof(arg0) <= sizeof(uint32_t)); \
static_assert(sizeof(arg1) <= sizeof(uint32_t)); \
static_assert(sizeof(arg2) <= sizeof(uint32_t)); \
my_macro_impl((uint32_t)(arg0), (uint32_t)(arg1), (uint32_t)(arg2)); \
} while (0)
But the user can use MY_MACRO with a bit-field and then my code fails to compile:
error: invalid application of 'sizeof' to bit-field
Question: Is there an option to detect at the compilation time if the size of the macro argument larger than, let's say, uint32_t?
P.S.
The MY_MACRO is going to act similarly to printf in a real-time embedded environment. This environment has a HW logger which may receive up to 5 parameters, each parameter should be 32 bits. The goal is to preserve the standard format as for printf. The format strings are parsed offline and the parser is well aware that every parameter is 32 bits, so it will cast it based on the %... from the format string. Possible usages are below.
Not desired usage:
uint64_t time = systime_get();
MY_MACRO_2("Starting execution at systime %llx", time); // WRONG! only the low 32 bits are printed. I want to detect it and fail the compilation.
Expected usage:
uint64_t time = systime_get();
MY_MACRO_3("Starting execution at systime %x%x", (uint32_t)(time >> 32), (uint32_t)time); // OK!
The following approach may work for this need:
#define CHECK_ARG(arg) _Generic((arg), \
int64_t : (arg), \
uint64_t : (arg), \
default : (uint32_t)(arg))
Then, the MY_MACRO can be defined as
#define MY_MACRO(a0, a1, a2) do \
{ \
uint32_t arg1 = CHECK_ARG(a0); \
uint32_t arg2 = CHECK_ARG(a1); \
uint32_t arg3 = CHECK_ARG(a2); \
my_macro_impl(arg1, arg2, arg3);\
} while (0)
In such case, when passing for example uint64_t, a warning is fired:
warning: implicit conversion loses integer precision: 'uint64_t' (aka
'unsigned long long') to 'uint32_t' (aka 'unsigned int')
[-Wshorten-64-to-32]
Note:
Other types like double, 128/256 bit types can be handled similarly.
Appropriate warnings should be enabled.
EDIT:
Inspired by Lundin's comment and answer, the proposed above solution can easily be modified to a portable version which will cause compilation error and not just a compiler warning.
#define CHECK_ARG(arg) _Generic((arg), \
int64_t : 0, \
uint64_t : 0, \
default : 1)
So the MY_MACRO can be modified to
#define MY_MACRO(a0, a1, a2) do \
{ \
_Static_assert(CHECK_ARG(a1) && \
CHECK_ARG(a2) && \
CHECK_ARG(a3), \
"64 bit parameters are not supported!"); \
my_macro_impl((uint32_t)(a1), (uint32_t)(a2), (uint32_t)(a3)); \
} while (0)
This time, when passing uint64_t parameter MY_MACRO(1ULL, 0, -1), the compilation fails with error:
error: static_assert failed due to requirement '_Generic((1ULL), long
long: 0, unsigned long long: 0, default: 1) && (_Generic((0), long
long: 0, unsigned long long: 0, default:
1) && _Generic((-1), long long: 0, unsigned long long: 0, default: 1))' "64 bit parameters are not supported!"
The type of the ternary ?: expression is the common type of its second and third arguments (with integer promotion of smaller types). So the following version of your MY_MACRO will work in a 32-bit architecture:
static_assert(sizeof(uint32_t) == sizeof 0, ""); // sanity check, for your machine
#define MY_MACRO(arg0, arg1, arg2) \
do { \
static_assert(sizeof(0 ? 0 : (arg0)) == sizeof 0, ""); \
static_assert(sizeof(0 ? 0 : (arg1)) == sizeof 0, ""); \
static_assert(sizeof(0 ? 0 : (arg2)) == sizeof 0, ""); \
my_macro_impl((uint32_t)(arg0), (uint32_t)(arg1), (uint32_t)(arg2)); \
} while (0)
Moreover, this solution should work with all versions of C and C++ (with, if necessary, a suitable definition of static_assert).
Note this macro, like the OP's original, has function semantics in that the arguments are evaluated only once, unlike for example the notorious MAX macro.
Question: Is there an option to detect at the compilation time if the size of the macro argument larger than, let's say, uint32_t?
The only way to do this portably, is by generating a compiler error with _Generic. If you want the error to be pretty and readable, you feed the result of _Generic to _Static_assert, so that you can type out a custom string as compiler message.
Your specification seems to be this:
Everything must be compile-time checks.
The macro can get 1 to 5 parameters of any type.
Only int32_t and uint32_t are allowed types.
This means that you have to write a variadic macro and it must accept 1 to 5 parameters.
Such a macro can be written like this:
#define COUNT_ARGS(...) ( sizeof((uint32_t[]){__VA_ARGS__}) / sizeof(uint32_t) )
#define MY_MACRO(...) \
_Static_assert(COUNT_ARGS(__VA_ARGS__)>0 && COUNT_ARGS(__VA_ARGS__)<=5, \
"MY_MACRO: Wrong number of arguments");
COUNT_ARGS creates a temporary compound literal of as many objects as you give the macro. If they are wildly incompatible with uint32_t you might get compiler errors/warnings here already. If not, COUNT_ARGS will return the number of arguments passed.
With that out of the way, we can do the actual, portable type check of each item in the variable argument list. To check the type of one single item with _Generic:
#define CHECK(arg) _Generic((arg), uint32_t: 1, int32_t: 1, default: 0)
Then pass the result of that on to _Static_assert. However, for 5 arguments we would need to check 1 to 5 items. We can "chain" a number of macros for this purpose:
#define CHECK(arg) _Generic((arg), uint32_t: 1, int32_t: 1, default: 0)
#define CHECK_ARGS1(arg1,...) CHECK(arg1)
#define CHECK_ARGS2(arg2,...) (CHECK(arg2) && CHECK_ARGS1(__VA_ARGS__,0))
#define CHECK_ARGS3(arg3,...) (CHECK(arg3) && CHECK_ARGS2(__VA_ARGS__,0))
#define CHECK_ARGS4(arg4,...) (CHECK(arg4) && CHECK_ARGS3(__VA_ARGS__,0))
#define CHECK_ARGS5(arg5,...) (CHECK(arg5) && CHECK_ARGS4(__VA_ARGS__,0))
Each macro checks the first argument passed to it, then forwards the rest of them, if any, to the next macro. The trailing 0 is there to shut up ISO C warnings about rest arguments required for variadic macros.
We can bake the calls to these into a _Static_assert that calls the proper macro in the "chain" corresponding to the number of arguments:
_Static_assert(COUNT_ARGS(__VA_ARGS__) == 1 ? CHECK_ARGS1(__VA_ARGS__,0) : \
COUNT_ARGS(__VA_ARGS__) == 2 ? CHECK_ARGS2(__VA_ARGS__,0) : \
COUNT_ARGS(__VA_ARGS__) == 3 ? CHECK_ARGS3(__VA_ARGS__,0) : \
COUNT_ARGS(__VA_ARGS__) == 4 ? CHECK_ARGS4(__VA_ARGS__,0) : \
COUNT_ARGS(__VA_ARGS__) == 5 ? CHECK_ARGS5(__VA_ARGS__,0) : 0, \
"MY_MACRO: incorrect type in parameter list " #__VA_ARGS__); \
Full code with examples of use:
#include <stdint.h>
#define COUNT_ARGS(...) ( sizeof((uint32_t[]){__VA_ARGS__}) / sizeof(uint32_t) )
#define CHECK(arg) _Generic((arg), uint32_t: 1, int32_t: 1, default: 0)
#define CHECK_ARGS1(arg1,...) CHECK(arg1)
#define CHECK_ARGS2(arg2,...) (CHECK(arg2) && CHECK_ARGS1(__VA_ARGS__,0))
#define CHECK_ARGS3(arg3,...) (CHECK(arg3) && CHECK_ARGS2(__VA_ARGS__,0))
#define CHECK_ARGS4(arg4,...) (CHECK(arg4) && CHECK_ARGS3(__VA_ARGS__,0))
#define CHECK_ARGS5(arg5,...) (CHECK(arg5) && CHECK_ARGS4(__VA_ARGS__,0))
#define MY_MACRO(...) \
do { \
_Static_assert(COUNT_ARGS(__VA_ARGS__)>0 && COUNT_ARGS(__VA_ARGS__)<=5, \
"MY_MACRO: Wrong number of arguments"); \
_Static_assert(COUNT_ARGS(__VA_ARGS__) == 1 ? CHECK_ARGS1(__VA_ARGS__,0) : \
COUNT_ARGS(__VA_ARGS__) == 2 ? CHECK_ARGS2(__VA_ARGS__,0) : \
COUNT_ARGS(__VA_ARGS__) == 3 ? CHECK_ARGS3(__VA_ARGS__,0) : \
COUNT_ARGS(__VA_ARGS__) == 4 ? CHECK_ARGS4(__VA_ARGS__,0) : \
COUNT_ARGS(__VA_ARGS__) == 5 ? CHECK_ARGS5(__VA_ARGS__,0) : 0, \
"MY_MACRO: incorrect type in parameter list " #__VA_ARGS__); \
} while(0)
int main (void)
{
//MY_MACRO(); // won't compile, "empty initializer braces"
//MY_MACRO(1,2,3,4,5,6); // static assert "MY_MACRO: Wrong number of arguments"
MY_MACRO(1); // OK, all parameters int32_t or uint32_t
MY_MACRO(1,2,3,4,5); // OK, -"-
MY_MACRO(1,(uint32_t)2,3,4,5); // OK, -"-
//MY_MACRO(1,(uint64_t)2,3,4,5); // static assert "MY_MACRO: incorrect type..."
//MY_MACRO(1,(uint8_t)2,3,4,5); // static assert "MY_MACRO: incorrect type..."
}
This should be 100% portable and doesn't rely on the compiler giving extra diagnostics beyond what's required by the standard.
The old do-while(0) trick is there to allow compatibility with icky-style brace formatting standards such as if(x) MY_MACRO(1) else. See Why use apparently meaningless do-while and if-else statements in macros?

Extract a function name inside a macro

In C, we often have to run such code
if (! somefun(x, y, z)) {
perror("somefun")
}
Is it possible to create a macro which, used as follows:
#define chkerr ...
chkerr(somefun(x, y, z));
would compile to the above?
I already know I can use __VA_ARGS__ macro, but this would require me to call it like
chkerr(somefun, x, y, z)
Short variant (you spotted already):
#define chkErr(FUNCTION, ...) \
if(!FUNCTION(__VA_ARGS__)) \
{ \
perror(#FUNCTION); \
}
Be aware that this can impose big problems in nested if/else or similar constructs:
if(x)
chkErr(f, 10, 12) //;
//^ semicolon forgotten!
else
chkErr(f, 12, 10);
would compile to code equivalent to the following:
if(x)
{
if(!f(10, 12))
perror("f");
else if(!f, 12, 10))
perror("f");
}
Quite obviously not what was intended with the if/else written with the macros... So you really should prefer to let it look like a real function (requiring a semicolon):
#define chkErr(FUNCTION, ...) \
do \
{ \
if(!FUNCTION(__VA_ARGS__)) \
{ \
perror(#FUNCTION); \
} \
} \
while(0)
You would call it like this:
chkErr(someFunction, 10, 12);
In case of error, output would be:
someFunction: <error text>
However, this hides the fact that a function actually gets called, making it more difficult to understand for "outsiders". Same output, not hiding the function call, but requiring one additional comma in between function and arguments (compared to a normal function call):
#define chkErr(FUNCTION, ARGUMENTS) \
do \
{ \
if(!FUNCTION ARGUMENTS) \
{ \
perror(#FUNCTION); \
} \
} \
while(0)
chkErr(someFunction,(12, 10));
// ^ (!)
Another variant with the charm of retaining the function call would print out this entire function call:
#define chkErr(FUNCTION_CALL) \
do \
{ \
if(!FUNCTION_CALL) \
{ \
perror(#FUNCTION_CALL); \
} \
} \
while(0)
chkErr(someFunction(10, 12));
In case of error, output would be:
someFunction(10, 12): <error text>
Addendum: If you really want exactly the output as shown in the question and still have the function call retained (without comma in between), you are a little in trouble. Actually, it is possible, but it requires some extra work:
Problem is how the preprocessor operates on macro arguments: Each argument is a token. It can easily combine tokens, but cannot split them.
Leaving out any commas results in the macro accepting one single token, just as in my second variant. Sure, you can stringify it, as I did, but you get the function arguments with. This is a string literal, and as the pre-processor cannot modify string literals, you have to operate on them at runtime.
Next problem then is, though, string literals are unmodifiable. So you need to modify a copy!
The following variant would do all this work for you:
#define chkErr(FUNCTION_CALL) \
do \
{ \
if(!FUNCTION_CALL) \
{ \
char function_name[] = #FUNCTION_CALL; \
char* function_name_end = strchr(function_name, '('); \
if(function_name_end) \
*function_name_end = 0; \
perror(function_name); \
} \
} \
while(0)
Well, decide you if it is worth the effort...
By the way - whitespace between function name and opening parenthesis is not eliminated. If you want to be perfect:
unsigned char* end = (unsigned char*) function_name;
while(*end && *end != '(' && !isspace(*end))
++end;
*end = 0;
Or, much nicer (thanks chqrlie for the hint):
function_name[strcspn(function_name, "( \t")] = 0;
Anything else I can think of would require an additional pre-processing step:
#define CAT(X, Y) CAT_(X, Y)
#define CAT_(X, Y) X ## Y
#define chkErr(FUNCTION_CALL) \
do \
{ \
if(!FUNCTION_CALL) \
{ \
perror(CAT(CHK_ERR_TEXT_, __LINE__)); \
} \
} \
while 0
chkErr(function(10, 12));
Ah, huh, this would result in code like this:
if(!function(10, 12))
{
perror(CHK_ERR_TEXT_42);
}
And now, where to get these macros from? Well, the pre-processing, remember? Possibly a perl or python script, e. g. generating an additional header file you'd have to include. You would have to make sure this pre-processing is done every time before the compiler's pre-processor runs.
Well, all not impossible to solve, but I'll leave this to the masochists among us...
C11 6.4.2.2 Predefined identifiers
The identifier __func__ shall be implicitly declared by the translator as if, immediately following the opening brace of each function definition, the declaration
static const char __func__[] = "function-name";
appeared, where function-name is the name of the lexically-enclosing function.
You can used it this way:
#define chkErr(exp) do { if (!(exp)) perror(__func__); } while (0)
chkerr(somefun(x, y, z));
Unfortunately, this would produce an error message with the name of the calling function, not somefun. Here is a simple variant that should work and even produce more informative error messages:
#define chkErr(exp) do { if (!(exp)) perror(#exp); } while (0)
chkerr(somefun(x, y, z));
In case somefun(x, y, z) returns a non zero value, the error message will contain the string "somefun(x, y, z)".
You can combine both techniques to give both the offending call and the location:
#include <errno.h>
#include <stdio.h>
#include <string.h>
#define chkErr(exp) \
do { if (!(exp)) \
fprintf(stderr, "%s:%d: in function %s, %s failed: %s\n",\
__FILE__, __LINE__, __func__, #exp, strerror(errno)); \
} while (0)
chkerr(somefun(x, y, z));
This assumes somefun() returns 0 or NULL in case of error and set errno accordingly. Note however that most system calls return non zero in case of error.
You can use the original call format:
chkerr(somefun(x, y, z));
With a macro and a helper function:
#define chkerr(fcall) \
if (!fcall) { \
perror(extract_fname(#fcall)); \
}
const char *extract_fname(const char *fcall);
The extract_fname function would get text and return everything until the open parenthesis.
Yes it is possible with an ugly, unsafe variadic macro:
#define chkerr(func, ...) \
if(!func(__VA_ARGS__)) \
{ \
perror(#func); \
}
...
chkerr(somefunc, 1, 2, 3);
But it is a very bad idea.
Call for sanity:
If there was just the original code with the plain if statement, the reader would think "Here they call a function and do some basic error control. Okay, basic stuff. Moving on...". But after the changes, anyone who reads the code will instead freeze and think "WTF is this???".
You can never write a macro that is clearer than the if statement - which makes the if statement superior to the macro.
Some rules to follow:
Function-like macros are dangerous and unreadable. They should only be used as the very last resort.
Avoid inventing your own secret macro language with function-like macros. C programmers who read your code know C. They don't know your secret macro language.
"To avoid typing" is often a poor rationale for program design decisions. Avoiding code repetition is a good rationale, but taking it to the extremes will affect code readability. If you avoid code repetition and make the code more readable at the same time, it is a good thing. If you do it but the code turns less readable, it is hard to justify.
It's not possible to extract just the function name. The C processor sees the literals you pass as single tokens, which can't be manipulated. Your only options are to print the function with arguments like Aconcague suggests or pass the name as a separate parameter:
#define chkErr(FUNCTION_NAME, FUNCTION_CALL) \
if(!FUNCTION_CALL) \
{ \
perror(#FUNCTION_NAME); \
}
chkErr(someFunction, someFunction(10, 12));

What does `##` mean in C?

This is an excerpt from linux kernel source. What is the stem## usage? seeing for first time in c
#define __pcpu_size_call_return(stem, variable) \
({ typeof(variable) pscr_ret__; \
__verify_pcpu_ptr(&(variable)); \
switch(sizeof(variable)) { \
case 1: pscr_ret__ = stem##1(variable);break; \
case 2: pscr_ret__ = stem##2(variable);break; \
case 4: pscr_ret__ = stem##4(variable);break; \
case 8: pscr_ret__ = stem##8(variable);break; \
default: \
__bad_size_call_parameter();break; \
} \
pscr_ret__; \
})
The preprocessor operator ## provides a way to concatenate actual arguments during macro expansion. If a parameter in the replacement text is adjacent to a ##, the parameter is replaced by the actual argument, the ## and surrounding white space are removed, and the result is re-scanned. For example, the macro paste concatenates its two arguments:
#define paste(front, back) front ## back
so paste(name, 1) creates the token name1.
The ## operator is a preprocessor operation which glues together tokens to form a single token.
So say you want to call two functions based on a common prefix, passing a single argument each time and allowing it to be changed.
You cannot use:
#define CallBoth(pref,arg) \
{ \
arg = pref A (arg); \
arg = pref B (arg); \
}
because the substituted pref and A (or B) will be distinct tokens. Similarly, you cannot use:
#define CallBoth(pref,arg) \
{ \
arg = prefA (arg); \
arg = prefB (arg); \
}
because no substitution of prefA or prefB will take place.
To do this, you use:
#define CallBoth(pref,arg) \
{ \
arg = pref##A(arg); \
arg = pref##B(arg); \
}
and the substituted pref and A (or B) are concatenated into a single token. That way, if you enter:
CallBoth(xyzzy,intVar);
it will be translated to:
{
intVar = xyzzyA(intVar);
intVar = xyzzyB(intVar);
}
Without this feature, there's no way to end up with a single token representing the function name.
As stated in a comment in the file you're referencing:
/* Branching function to split up a function into a set of functions that are called for different scalar sizes of the objects handled. */
So, depending on the size of the variable being given to the macro, it will call one of:
stem1(variable)
stem2(variable)
stem4(variable)
stem8(variable)
where stem and variable are supplied as a parameter to the macro. Or it will call __bad_size_call_parameter() if none of those sizes are relevant.
So, a call:
char char_var;
__pcpu_size_call_return(xyzzy,char_var)
will result in a call:
xyzzy1(char_var):
int int_var;
__pcpu_size_call_return(xyzzy,int_var)
will result in a call:
xyzzy4(int_var)
where sizeof(int) == 4.

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