Function-style macro with no-op if a condition is false - c

Suppose I have the following construct in multiple places in my code and want to make my code more legible:
#if HAVE_LIBFOOBAR
foobar_func(data);
#endif
I was thinking of writing a function-style macro around this, which would handle the conditionals, making the occurrences in the code look like a regular function call:
foobar_func_if_available(data)
If the condition is true, this would be replaced with a call to the actual function, else it would be a no-op.
Thus, something like:
#if HAVE_LIBFOOBAR
#define foobar_func_if_available(x) foobar_func(x)
#else
#define foobar_func_if_available(x) {}
#endif
Questions:
Does {} work as a no-op? Is it safe from having unintended effects (such as being used in an unbracketed if statement)? If not, what would I use?
Do I have to have two independent #defines wrapped in conditionals, or is there a way to do it the other way round (one #define with the conditionals inside the function-style macro)?
Edit: it has been suggested that this is a duplicate of another question, but in my opinion it is not: the other question asks “what is the problem solved with this construct”, mine is “what construct will solve my problem”. Indeed the other question has a possible solution to my problem, it does not cover all aspects of my question.

Create a dummy function and make the #define point at it (conditionally):
#if HAVE_LIBFOOBAR
#define foobar_func_if_available(x) foobar_func(x)
#else
int dummy(int ignored)
{
return 0;
}
#define foobar_func_if_available(x) dummy(x)
#endif
Or just :
#define foobar_func_if_available(x) 0

You cannot achieve it with a single #define.
You do not need {} as a no-op, you can define an empty expression in a number of ways:
#define foobar_func_if_available(x)
#define foobar_func_if_available(x) ;
#define foobar_func_if_available(x) do{}while(0)
There are circumstances where either of these may cause syntactic issues, but for void functions neither is likely to cause a problem - the solution breaks down for non-void functions however.
A better solution avoiding function-like macros altogether is to define the function body conditionally:
void foobar_func( int n )
{
#if defined HAVE_LIBFOOBAR
// do something
#else
// do nothing
#endif
}
whether the empty function results in no code is a matter for the compiler and the optimisation level applied, but importantly the code will work syntactically in all situations where a call to foobar_func() is valid. To worry about it being a no-op or not is probably sweating the small stuff.

Macros like ((int)0) or ((void)0) are probably the most flexible/safest no-op macros. They're flexible because you can use them
in expressions (unlike do{}while(0)) and they don't break if-else like {} or ; would.
Example of how {} (or ;) macros break if-else:
#define foo() {}
if(1) foo(); else bar(); //syntax error because if(1) {}; else bar(); was pasted
If the macro should emulate an integer returning function, it's better to use a casted integer literal over a plain integer constant as integer constants (and especially zeros) are usable in more contexts (case labels, bitfield sizes, array sizes , null pointer constants) than non-const integer expressions.
You don't need to have two macros as in:
#if HAVE_LIBFOOBAR
#define foobar_func_if_available(x) foobar_func(x)
#else
#define foobar_func_if_available(x) ((void)0) /*if foobar_func returns void*/
#endif
You can put the condition inside the macro:
#define foobar_func_if_available(x) \
(HAVE_LIBFOOBAR?foobar_func(x):((void)0))
Even a very dumb compiler should be able to optimize the constant conditional out.
But if you rely on an empty HAVE_LIBFOOBAR evaluating to 0 inside an #if, then the above won't work -- HAVE_LIBFOOBAR will need to be an integer.
(
You could do
#if !HAVE_LIBFOOBAR
#undef HAVE_LIBFOOBAR
#define HAVE_LIBFOOBAR 0
#endif
#define foobar_func_if_available(x) \
(HAVE_LIBFOOBAR?foobar_func(x):((void)0))
to normalize an empty HAVE_LIBFOOBAR into 0 but unless you will reuse the now assured HAVE_LIBFOOBAR's definedness, it seems like an unnecessary complication over the original two foobar_func_if_available macros.
)

Related

C preprocessor #if condition

I am building some generic things in C.
Here is the code:
// main.c
#include <stdio.h>
#define T int;
#include "test.h"
int main()
{
return 0;
}
// test.h
#define _array_is_pointer(T) ( \
{ \
T _value; \
__builtin_classify_type(_value) == 5; \
})
#ifdef T
#if _array_is_pointer(T)
struct array_s
{
T *items;
}
void array_push(struct array_s * array, T value)
{
// push method for pointer.
}
#else
struct array_s
{
T *items;
}
void array_push(struct array_s * array, T value)
{
// push method for non-pointer.
}
#endif
#endif
** edited: add more code in test.h **
I would like the preprocessor runs different code when T is pointer or non-pointer.
But I got an error token "{" is not valid in preprocessor expressions.
Is it possible to do that?
I would like the preprocessor runs different code when T is pointer or non-pointer.
Is it possible to do that?
No, it is not possible. Preprocessor is not aware of types.
If you really want this, pass a mark if T is a pointer or not as a separate macro.
#define T int*
#define T_IS_A_POINTER 1
#include "test.h"
Or have separate calls:
#define T int*
#include "test_a_pointer.h"
#define T int
#include "test_not_a_pointer.h"
The preprocessor doesn't know whether T is a pointer, because preprocessing happens before semantic analysis of the program. All the preprocessor sees are tokens; it knows that 42 is a number and take42, but that's it. The only definitions it knows about are preprocessor #defines.
Moreover, in C, functions --even builtin constant functions like sizeof and __builtin_classify_type-- cannot be evaluated by the preprocessor. The preprocessor cannot evaluate block expressions either, but there wouldn't be much point so it has no idea what a variable is and thus doesn't need declarations. The only identifier you can use in an #if preprocessor conditional are macro definitions which expand to integer constants (or entire expressions containing only arithmetic operations on integer constants).
There is the _Generic construct introduced in C11, which allows you to generate different expressions based on the type of a controlling expression. But it can only be used to generate expressions, not declarations, so it's probably not much help either.
There is no issue while writing multi-line code-snippet in
#define _array_is_pointer(T) ( \
{ \
T _value; \
__builtin_classify_type(_value) == 5; \
})
But, as you have know, the first step done before passing the code to compiler is to create an Expanded source code. In this step, all the five lines woud be pasted whereever you would have written _array_is_pointer(T) and hence resulting code would have :
#if (
{
T _value;
__builtin_classify_type(_value) == 5;
})
and here is a blunder. One can not write multiple lines like this in if clause, nor you could do this using {}. And hence, you got the error token "{" is not valid in preprocessor expressions.
Hence, you would have to write a single expression to in if clause preprocessor.

C macro expansion including compiler switches

My current implementation defines a couple of variables depending on corresponding compiler switches:
#ifdef ENABLE_var1
int var1;
#endif
#ifdef ENABLE_var2
int var2;
#endif
The compiler switches will be set by -D option during make. The names will always consist of the same prefix and the variable name. Since it is always the same strategy, my idea is to replace this using a macro like:
DECLARE(var1)
DECLARE(var2)
Calling make -DENABLE_var1 should result in:
int var1;
Calling make -DENABLE_var1 -DENABLE_var2 should result in:
int var1;
int var2;
Since it is not possible to use #ifdef within a macro, is there a trick to achieve this?
As long as the variable names to be defined, potentially, are known, then this can be accomplished:
// Define a DEFINE_x macro for each x that might be enabled.
#if defined ENABLE_var1
#define DEFINE_var1 int var1;
#else
#define DEFINE_var1
#endif
#if defined ENABLE_var2
#define DEFINE_var2 int var2;
#else
#define DEFINE_var2
#endif
// Define DECLARE(x) to expand to the corresponding DEFINE_x macro.
#define DECLARE(x) DEFINE_##x
// List potential definitions.
DECLARE(var1)
DECLARE(var2)
If the names are not known, then this kludge works:
#define Comma() ,
#define Argument3c(a, b, c,...) c
#define Argument3b(a, b,...) Argument3c(a, b, __VA_ARGS__)
#define Argument3a(a,...) Argument3b(a, __VA_ARGS__)
#define Nullify1
#define NullifyHelper(x) Nullify##x
#define Nullify(x) NullifyHelper(x)
#define DECLARE(x) Argument3a(Comma Nullify(ENABLE_##x) (), int x;,,)
DECLARE(var1)
DECLARE(var2)
Understanding this requires following the preprocessing in great detail, but I will provide a few notes:
For -Dname, GCC defines name to be replaced by 1. The Nullify macro, with its helpers, causes ENABLE_x to be replaced by an empty sequence if ENABLE_x is defined to be 1 and by a non-empty sequence otherwise.
Then, if an empty sequence has resulted, we have Comma (), which expands to a comma. If it is not an empty sequence, we have Comma something (), which does not allow the function-like macro to be expanded, so some sequence not including a comma results.
Through the remaining macro expansions, this comma or lack thereof determines which argument is where in the argument list, allowing us to pick out either the desired definition or an empty sequence.
I advise against using this in production code. There is likely a better way to accomplish your configuration goal.

What is the difference between global variables and #define in c

Whats the reason why there are 2 opportunities :
global variables
symbolic constants with #define ?
So I know what #define does but I don't know what the difference in use is.
Which situation do I must have thus I'm able to decide myself upon the right opportunitie? What is one of the opportunities able to do what the other one doesn't ? I hope that I could clarify what I mean.
Well, global variables can be edited from everywhere.
Basically, in the low level, a variable is stored in RAM memory and created after launching your application, it always has an address in RAM. Defines are just macros, your compiler will just replace your define names with its values in the compilation step.
#define can't be edited, it's just a macros. And #define is not just about values, you can define almost everything that you want, for example:
// Defining a constant
#define PI 3.14
// Defining an expression
#define MIN(x,y) ((x)<(y))?(x):(y)
// Defining a piece of code
#define STOP_TIMER \
clock_gettime(CLOCK_REALTIME, &__t1); \
__lasttime = \
(double) (__t1.tv_sec - __t0.tv_sec) + \
(double) (__t1.tv_nsec - __t0.tv_nsec) / 1000000000.0;
And, in most situations, defines are used to set some OS-specific or hardware-specific values. It's a really powerful thing, because it gives you the opportunity to change things dynamically in the compilation step. For example:
// Example with OS
#ifdef __linux__
#define WELCOME_STRING "welcome to Linux!"
#else
#define WELCOME_STRING "welcome to Windows!"
#endif
// Example with hardware
#if __x86_64__ || __ppc64__
#define USING_64BIT
#else
#define USING_NOT64BIT
#endif
Consider this small example
#define num 5
int number = 5;
num is a macro and number is a global variable.
One important difference is that num is not stored in the memory, num is just the substitute for 5, but number uses memory.
Also, macro's are preprocessor directives, their values cannot be changed like variables.
So, no doing
num = 6;
later in the code. You will have to use #undef to undefine it and define it again to change the value.
Global variables can be accessed and edited from everywhere. #define constants can't be edited, just read.
Examples:
We use #define ERROR 666 to define a programmer pre compile time constant for an error for the whole program.
We use a global variable for a count of how many operations a function did and this value can be read by other functions as well.
There's no point to make the error as a global variable since it shouldn't be edited and you can't use the #define x as a counter.
#define is declared on top of the code, it means before the declaration of the class. And it serves as to define (as the name says) a constant, that can be read but not changed.
A global variable can be accessed globally on the code, and at same time changed.

Double slash comment substituition within a macro

I am developing a PIC MCU program on an ansi-compliant compiler (Microchip XC8).
There are two operation modes, determined via macros during compilation time.
So that I don't want to duplicate one function-like macro due to one line of code, I would like to know if there is any way to write a macro such as
#define FOO //
so that when FOO is substituted it will actually cancel the rest of the line.
Writing a function instead of a macro is out of the question because the delay generated by function calls would disrupt the tight timings of my program (around some microseconds).
You can't make a macro expand to comment out the line, no. // in a macro definition is a comment following the definition, it's not expanded, and IIRC there's a rule saying that you cannot construct a // using token-pasting. Even if you can, expanding it doesn't mean that the macro starts a comment. Basically, you don't get to change the comment syntax using macros.
You could do:
#if DO_NOTHING_MODE
#define FOO(ARG1)
#else
#define FOO(ARG1) ARG1
#endif
and use it like:
#define FUNCTION_LIKE_MACRO(ARG1, ARG2) \
required line; \
FOO(optional line;) \
Although a more common idiom is to design the macro to accept an expression as its argument, rather than a whole line:
#if DO_NOTHING_MODE
#define FOO(ARG1) ((void)0)
#else
#define FOO(ARG1) (ARG1)
#endif
and use it like FOO(optional line);
Either way, if the macro argument has commas in it, then the caller needs to enclose them in parentheses FOO((1,2)), although in C99 you can avoid that by making FOO a variadic macro:
#define FOO(...) (__VA_ARGS__)
You can use the #ifndef directive to achieve the same effect:
#ifndef FOO
your_line_of_code
#endif
EDIT: #SteveJessop made me see I didn't pay attention to this sentence of the OP "I don't want to duplicate one function-like macro due to one line of code". Here is what could be done in that case, if duplicating the function-like macro is not wanted:
// When FOO is defined, BLA in FUNC macro is a no-operation (null statement)
#ifndef FOO
#define BLA() a++
#else
#define BLA()
#endif
#define FUNC() \
BLA(); \
b++;
Comments are removed from the source before macro replacement occurs, so there's no way to define a macro exactly like that. However, it is certainly possible to pass an additional parameter into the macro to specify which code it should generate, or conditionally define the macro depending on the mode for which you are compiling.
#define FOO(...) __VA_ARGS__
And then use FOO(your code here) instead of FOO your code here in the macro.
If your platform doesn't have C99, you can instead use
#define FOO(x) x
and just make sure the argument doesn't contain a , not enclosed in ().

How do I do different things per macro value?

#define TYPE char *
if TYPE is char *
do A
if TYPE is int
do B
Is there an example how to do such things?
C preprocessor MACROS manipulate text, so are essentially typeless, so NO you can't do that.
You could associate another symbol with it:
#define TYPE char *
#define TYPE_IS_CHAR_STAR
#ifdef TYPE_IS_CHAR_STAR
...
#endif
You just need to keep them consistent manually.
Note that that's a dangerous macro; you should use a typedef instead. With the macro:
TYPE x, y;
x is a pointer, but y isn't.
You can get a similar effect by defining another macro along with the type, and using #ifdef etc. with that other macro. For example:
#define TYPE char *
#define TYPE_IS_PCHAR 1
...then later...
#ifdef TYPE_IS_PCHAR
do A
#endif
#ifdef TYPE_IS_INT
do B
#endif
It's not quite the same thing, but it still gets you there.
Not easily. You could do something like:
#define TYPE_IS_CHARPTR
//#define TYPE_IS_INT
#ifdef TYPE_IS_CHARPTR
do A
#endif
#ifdef TYPE_IS_INT
do B
#endif
But you really should be trying to minimise your use of the preprocessor for tricky things (anything other than simple variables).
With enumerated constants and inline functions, there's little need for such uses nowadays.
It would work if you just used basic types (since they're just strings - see Mitch's answer). But as soon as you try to use pointers, it won't work any more - the asterisk throws the preprocessor for a loop:
[holt#Michaela ~]$ gcc test.c
test.c:3:10: error: operator '*' has no right operand
But if you want do do different things based on different types, I'm going to have to recommend switching to C++ and using templates and template specialization. Reluctantly, since template syntax is incredibly ugly, but you should be able to do whatever you want.
Hope that helps!

Resources