getting the variable values in #define definition - c

Here is what I am trying to do.
step1) I want to call a macro with a conditional statement(simple are compounded) like
for eg:
MACRO1(a==1)
MACRO1((i!=NULL) && (j>10))
step2) Here is how i am defining this macro
#define MACRO1(condition) \
if(!(condition)) ??????????????????????????
Here in the definition of the macro, if the condition statement fails. I want to print the variable values so that I will be useful to know the exact reason.
I used #condition in the definition, but it just printing the condition, instead of the values of the variables used in the condition. Please help.

You could do something along these lines:
#define MACRO1(condition, msg) \
if(!(condition)) { printf msg; }
and use it as follows:
MACRO1(a==1, ("a: %d\n", a))
MACRO1((i != NULL) && (j>10), ("i: %p, j: %d\n", i, j));
The C preprocessor is just a simple substitution engine, without the capability of analyzing the contents of expressions.

You shouldn't define macros that look like a function, but behave differently, in particular in your case may change control flow: an else that follows a macro that contains an if can apply to something different than the programmer (yourself after a week) thinks. Protect the if such that a dangling else will not apply to it
#define MACRO1(COND, ...) \
do { \
if (!(COND)) printf(stderr, "condition " #COND ": " __VA_ARGS_); \
} while (0)
This macro should always be called with a format string as second argument and the names of the variables that you want to see
MACRO1((toto != 78.0), "toto=%9\n", toto);
this should print you something like
condition (toto != 78.0): toto=3.14

There is no way that I know of to separate the variables from the condition.
However, you can pass them in as extra parameters:
#define MACRO(condition, printsyntax, ...) \
if(!(condition)) {\
printf("condition %s not met! (" printsyntax ")\n", #condition, __VA_ARGS__); \
};
You would use it as:
MACRO((i!=NULL) && (j>10), "i=%p, j=%d", i, j)
with an example result being:
condition (i!=NULL) && (j>10) not met! (i=(nil), j=11)
The compiler will splice together the constant strings into one string for the printf,
the condition will automatically be printed and the rest of the arguments are your job to get right.
Edit
After Jens' remark about the else I modified the code a bit to not allow for such structures without using do{}while();.

Related

portability and safety of C macro using lambda parameter

Preface
I know that there are several libraries for auto-testing available.
Let's ignore that for this question, please.
Motivation
Implementing some library I got tired of manual testing, so I started to write a "self-test" program, starting with code using many assert()s.
Unfortunately when an assert() fails, only limited information is shown on the screen, and I would typically have to use the debugger to examine the core dump to get more details of the failure.
So I added a macro that allows a printf()-like output (implemented via the E() (for error) macro) when an assertion fails; I named that macro VA() (for verbose assertion):
#define VA(assert_cond, msg, ...) do { \
if ( !(assert_cond) ) E(msg, ##__VA_ARGS__); \
assert(assert_cond); \
} while (0)
Using that would look like this:
VA(FASTWORD(FASTWORD_BITS - 1) == 0, "%s: FASTWORD() failed", __func__);
As the self-test program used array-like data structures, I needed to inspact those as well, so I output those before doing the tests, resulting in a lot of output even when all tests succeed.
So I invented another macro, VFA() (verbose failed assertion) that uses a "lambda parameter" like this:
#define VFA(assert_cond, cmd, msg, ...) do { \
if ( !(assert_cond) ) { \
E(msg, ##__VA_ARGS__); \
cmd; \
} \
assert(assert_cond); \
} while (0)
While writing that I wondered how the preprocessor would parse commata for a use case like this:
VFA(fw[0] == out_fw0 && fw[1] == out_fw1,
dump_fastwords_range(fw, 4, pos, (pos + count) % FASTWORD_BITS),
"%s: __clear_fw_bits_up(%d, %d) failed", context, pos, count);
I mean it could be possible that the condition could be the first parameter, dump_fastwords_range(fw could be the second, 4 could be the third, and so on...
However that is not the case with gcc at least.
The other thing is cmd; in the macro:
My first version did not include the semicolon, so I would have to write (which looks really ugly):
VFA(fw[0] == out_fw0 && fw[1] == out_fw1,
dump_fastwords_range(fw, 4, pos, (pos + count) % FASTWORD_BITS);,
"%s: __clear_fw_bits_up(%d, %d) failed", context, pos, count);
OK, here's another use example of my macro:
VFA(fw[0] == out_fw0 && fw[1] == out_fw1,
{
const unsigned first = pos >= count ?
pos - count : FASTWORD_BITS + pos - count + 1;
dump_fastwords_range(fw, 4, first, pos);
},
"%s: __clear_fw_bits_dn(%d, %d) failed", context, pos, count);
Questions
The questions I have are:
Is parsing of the macro parameters portable across compilers?
Will the cmd use create any trouble, considering the parameter could be rather complex (as the last example suggests)?
Is parsing of the macro parameters portable across compilers?
No. ##__VA_ARGS__ is a non-portable gcc extension. What does ##__VA_ARGS__ mean?
Will the cmd use create any trouble, considering the parameter could be rather complex (as the last example suggests)?
Items within () of that macro parameter will mean that it all gets treated like a single pre-processor token and expanded as such. You can peek at the pre-processor output if you are curious. Formally this is specified in C17 6.10.3/10:
Each subsequent instance of the
function-like macro name followed by a ( as the next preprocessing token introduces the
sequence of preprocessing tokens that is replaced by the replacement list in the definition
(an invocation of the macro). The replaced sequence of preprocessing tokens is
terminated by the matching ) preprocessing token, skipping intervening matched pairs of left and right parenthesis preprocessing tokens.
So it shouldn't create any trouble unless you do truly evil stuff like using goto or setjmp etc from inside it.

how to pass arguments to function and use these arguments in macro function inside it

I want to do something like that
#define GREATER_THAN_ZERO(a) a>0? 1:0
and use this macro inside another function like that
void test(int x)
{ if (GREATER_THAN_ZERO(x) == 1) printf("more than zero");
else printf("less than zero");
}
But when I use test function it always prints "less than zero"
NOTE: this is an example not the real case but I want to do something like that (use macro inside a function)
Can anyone help me please?
EDIT
I have configuration file like that
#define LED_u8_MODE_0 LED_u8_REVERSE
#define LED_u8_MODE_1 LED_u8_NORMAL
and in program I have a macro function
#define LED_u8_GET_MODE(LED_u8_INDX) (LED_u8_INDX == 0)? LED_u8_MODE_0: \
(LED_u8_INDX == 1)? LED_u8_MODE_1: \
(LED_u8_INDX == 2)? LED_u8_MODE_2: \
(LED_u8_INDX == 3)? LED_u8_MODE_3: 800
then I use it inside this function
void LED_voidSetLedOnWithIndx(u8 Copy_u8LedIndx)
{
if(LED_u8_GET_MODE(Copy_u8LedIndx) == LED_u8_NORMAL)
{
DIO_voidSetPinValue(Copy_u8LedIndx, DIO_u8_HIGH);
}
else //if(LED_u8_GET_MODE(Copy_u8LedIndx) == LED_u8_REVERSE)
{
DIO_voidSetPinValue(Copy_u8LedIndx, DIO_u8_LOW);
}
}
I can't reproduce the problem with the code you posted, but you mentioned it's not the real case, and I do have an idea of the problem.
The expression is not being associated as you intended. When expanded, the expression is:
x>0? 1:0 == 1
which groups as:
x>0? 1:(0 == 1)
which is equivalent to:
x>0? 1:0
This still works as intended. But if you instead had:
if (GREATER_THAN_ZERO(x) == 0)
then you would end up with:
x>0? 1:0 == 0
or:
x>0? 1:(0 == 0)
which is always 1.
There are two fundamental problems with the macro definition: (1) it isn't protecting its argument from mis-association, and (2) it isn't protecting the result from mis-association.
The proper way to write it would be:
#define GREATER_THAN_ZERO(a) ((a) > 0 ? 1 : 0)
The parentheses around (a) allow you to pass an expression as the argument without worrying about it being re-associated. The parentheses around the entire macro body allow you to use the macro in an expression without it being re-associated.
In this particular case, the ?: operator is redundant, since n > 0 always returns either 0 or 1, so you could just use:
#define GREATER_THAN_ZERO(a) ((a) > 0)
with identical results.
Similarly, the comparison of the result with 1 serves no purpose and suggests that something unusual is going on. It is much more natural to simply write:
if (GREATER_THAN_ZERO(x))
This implicitly tests to see if it's non-zero. Remember, if (n) is equivalent to if (n != 0).
Too large for a comment, so as answer: I recommend a different formatting (with parentheses adjusted, though):
#define LED_u8_GET_MODE(LED_u8_INDX) \
( \
(LED_u8_INDX) == 0 \
? (LED_u8_MODE_0) \
: (LED_u8_INDX) == 1 \
? (LED_u8_MODE_1) \
: (LED_u8_INDX) == 2 \
? (LED_u8_MODE_2) \
: (LED_u8_INDX) == 3 \
? (LED_u8_MODE_3) \
: 800 \
)
Or do you disagree that this is easier to read?
Still, those many ternary operators are difficult to read and handle, I'd rather consider replacing the entire macro with an inline function:
inline int ledGetMode(int index)
// (if need be, adjust parameter and return value types appropriately)
{
switch(index)
{
case 0:
return LED_u8_MODE_0;
// ...
default:
return 800;
}
}
Looks much cleaner and should, as inline, not have any overhead over the macro...
The main advantage, though, is that you simply skip any trouble with bad association of parameters or result and with multiple evaluation of the parameters!

Preprocessor Directives to define function macros with multiple if/else if statements

I am using Preprocessor Directives to define function macros in C. Can I have multiple if/else if statements in a function macro?
If yes how do I write it?
#define WRITE(str,id) #str(id)
// HERES where I am having difficulty
#define DRAW_GENERIC_WINDOW(windowID, type) if type==1 WRITE(draw_text,windowID) else if type==2 WRITE(draw_image,windowID) else if type==3 WRITE(draw_hyperlink,windowID)
// usage
DRAW_GENERIC_WINDOW(112, 1);
DRAW_GENERIC_WINDOW(178, 2);
DRAW_GENERIC_WINDOW(988, 3);
// At compile time the above should be converted to...
draw_text(112);
draw_image(178);
draw_hyperlink(988);
I am aware how to perform a single if else statement in a Function Macro but not how to do it with multiple if/else if's:
// if else eg
#define DRAW_GENERIC_WINDOW(windowID, type) ((type)==(1))?WRITE(draw_text,windowID):WRITE(draw_image,windowID)
Note: Before you ask "Why the hell are you programming like this?" :P its because I am writting in a language that is very similar to C called 4dm, except there are no structs, pointers or the ability to declare new data types. So I am forced to resort to Preprocessor Directives in order to achieve some form of virtual functions(used when I dont know the type of window - image, hyperlink, etc. - that I am working with).
Try it out like this:
#define WRITE(str,id) str(id)
// HERES where I am having difficulty
#define DRAW_GENERIC_WINDOW(windowID, type) if (type==1) \
WRITE(draw_text,windowID) \
else if (type==2) \
WRITE(draw_image,windowID) \
else if (type==3) \
WRITE(draw_hyperlink,windowID)
// usage
DRAW_GENERIC_WINDOW(112, 1);
DRAW_GENERIC_WINDOW(178, 2);
DRAW_GENERIC_WINDOW(988, 3);
Just use the token pasting operator ## as basic pattern matching, like this:
#define DRAW_GENERIC_WINDOW(windowID, type) DRAW_GENERIC_WINDOW_ ## type(windowID)
#define DRAW_GENERIC_WINDOW_1 draw_text
#define DRAW_GENERIC_WINDOW_2 draw_image
#define DRAW_GENERIC_WINDOW_3 draw_hyperlink
Then use it like this:
DRAW_GENERIC_WINDOW(112, 1); // expands to draw_text(112, 1);
DRAW_GENERIC_WINDOW(178, 2); // expands to draw_image(178);
DRAW_GENERIC_WINDOW(988, 3); // expands to draw_hyperlink(988);

Variable no of argument in C Macro

I am writing some hardware specific code, where I want to use C Macros, the macro definition would be something like this:-
#define VALIDATE_RESOURCE_AND_ALLOCATE(MODE,RESOURCE1) if(a[MODE][RESOURCE1] != x1) || \
(a[MODE][RESOURCE1] != y1)) \
a[MODE][RESOURCE1]=x3;
Since sometimes I can have more then 1 resource to allocate, such as:-
#define VALIDATE_RESOURCE_AND_ALLOCATE_1(MODE,RESOURCE1,RESOURCE2) if(a[MODE][RESOURCE1] != x1) || \
(a[MODE][RESOURCE1] != y1)) \
a[MODE][RESOURCE1]=x3;
if(a[MODE][RESOURCE2] != x1) || \
(a[MODE][RESOURCE2] != y1)) \
a[MODE][RESOURCE2]=x3;
Is there any way I can write a macro, which covers both cases, as it takes variable number of arguments?
I have used variable number of arguments, in macro for printf macros, but then how I will address those arguments, by their respective name, for example, if I modify the MACRO definition such as:0-
#define VALIDA_RESOURCE_AND_ALLOCATE(MODE,.....)
How will I identify RESOURCE1, RESOURCE2?
Your macros have a lot of repeated code in them. Simplifying them helps make a solution more apparent:
#define VALIDATE_RESOURCE_AND_ALLOCATE_1(MODE,RESOURCE1,RESOURCE2) do {\
VALIDATE_RESOURCE_AND_ALLOCATE(MODE, RESOURCE1); \
VALIDATE_RESOURCE_AND_ALLOCATE(MODE, RESOURCE2); \
} while(0)
Here, it's clearer that this is simply a repeated invocation of the first macro while iterating through a list of arguments.
Assuming you know that the data types being used here will always be consistent, you can try something like this (untested and written off of the top of my head):
#ifdef HARDWARE_PLATFORM_A
static sometype args[] = {
RESOURCE1,
RESOURCE2,
/* ... etc, etc */
};
#elif defined HARDWARE_PLATFORM_B
static sometype args[] = {
RESOURCE10,
RESOURCE11,
/* ... etc, etc */
};
/* repeat for all hardware platforms */
#endif
void initialization_function (void) {
int i;
for (i = 0; i < (sizeof(args) / sizeof(args[0])); ++i) {
VALIDATE_RESOURCE_AND_ALLOCATE(MODE, args[i]);
}
}
where sometype is the data type of the arguments that you will be using for RESOURCE1, RESOURCE2, etc.
Given the complexity of what you are trying to do, you'd be a lot better off writing a function to do the iteration instead of a macro. You can still use a macro to create the RESOURCE list, but don't try to get the pre-processor to do the iteration for you. If you need to avoid the overhead of a function call (since you tagged this as 'embedded'), you can declare the functions inline and the result should be as efficient as using a macro. In the process, though, you'll gain things like type safety.
While it might be technically possible to do this with a macro, it would be a nasty hack that would most likely bring more problems than benefits. Doing complex procedural tasks with the pre-processor rarely turns out well.
The other alternative that you have is to use a code generator that takes a list of RESOURCE arguments from a file and generates a .c file containing the initialization code. The code generator would be written in a language much more powerful than the C pre-processor (almost any scripting language could be used here). This probably wouldn't be worth the trouble unless you had a long list of RESOURCEs, though.
One way you could accomplish it is don't pass in a variable number of arguments, but stick with two and make the second one be a list that can be used in an initialization. For example (trailing backslashes left off for clarity):
#define VALIDATE_RESOURCE_AND_ALLOCATE(MODE, LIST)
{
int resources[] = LIST;
int count;
for(count = 0; count < sizeof(resources)/sizeof(int); count++) {
/* do stuff here for each resources[count] */
}
}
And then you can simply call it as such:
VALIDATE_RESOURCE_AND_ALLOCATE(MODE, { RESOURCE1, RESOURCE2 } )
Note: there is more than one way to skin this cat, so pick your favorite answer and go with it :-)
Would this be too silly? ;-)
#define VALIDATE_RESOURCE_AND_ALLOCATE(MODE,RESOURCE1,RESOURCE2) \
if(a[MODE][RESOURCE1] != x1) || (a[MODE][RESOURCE1] != y1)) \
a[MODE][RESOURCE1]=x3; \
if((RESOURCE1 != RESOURCE2) && (a[MODE][RESOURCE2] != x1) || (a[MODE][RESOURCE2] != y1))) \
a[MODE][RESOURCE2]=x3;
and Call it as below for single resource
VALIDATE_RESOURCE_AND_ALLOCATE(M1,R1,R1)
and like below for two?
VALIDATE_RESOURCE_AND_ALLOCATE(M1,R1,R2)

Creating function-like macros

gcc 4.4.2 c89
I have this code snippet that I have to repeat in a lot of my code. I am just wondering is there a way to make it short by using a macro function?
There is the code I would like to change.
ERR_INFO error_info; /* create error object */
ErrorInfo(&error_info); /* pass the address for it to be filled with error info */
fprintf(stderr, "And the error is? [ %s ]\n", error_info.msg); /* display the error msg */
And my attempt to create a macro function to use it.
#define DISPLAY_ERR(error_info) ErrorInfo(&error_info) error_info.msg
fprintf(stderr, "And the error is? [ %s ]\n", DISPLAY_ERR); /* display the error
Any suggestions would be most helpful,
If you really want a macro:
#define DISPLAY_ERR(error_info) \
do \
{ \
ErrorInfo(&(error_info)); \
fprintf(stderr, "And the error is? [ %s ]\n", (error_info).msg); \
} while(0)
You need the do... while(0) because of a good reason.
Then, you call your macro when you want to print the error:
if (error) {
DISPLAY_ERR(error_info);
/* more statements if needed */
}
I am assuming that error_info has been defined somewhere. If not, or if you don't want to, then you can change your macro definition and use:
#define DISPLAY_ERR() \
do \
{ \
ERR_INFO error_info;
ErrorInfo(&error_info); \
fprintf(stderr, "And the error is? [ %s ]\n", error_info.msg); \
} while(0)
if (error) {
DISPLAY_ERR();
/* more statements if needed */
}
There's a couple of ways you could do this. You could use the comma operator:
#define DISPLAY_ERR(error_info) (ErrorInfo(&(error_info)),(error_info).msg)
...or you could change the ErrorInfo() function so that it's return value is the pointer you pass it:
#define DISPLAY_ERR(error_info) (ErrorInfo(&(error_info))->msg)
(and a few more options besides).
Are you trying to create a macro which "returns" a value? In C++ you can use the comma operator , to evaluate the left expression and then return the right expression. You can do the same in C, too.
(foo(var), var.field) // foo(...)is evaluated first,
// then second expression is returned
also
DISPLAY(message) // Pass an argument to macro
You need to make it work like a function call, so it can be used anywhere a function call can, except with no value returned. You also need to mark the ends of intermediate lines with a backslash. And the 'do { ... } while (0) idiom is useful in this context:
#define DISPLAY_ERR() do { ERR_INFO error_info; ErrorInfo(&error_info); \
fprintf(stderr, "And the error is? [ %s ]\n", error_info.msg); } while (0)
The error_info variable is local to the block, so you don't have to remember to declare it in the functions where you use the macro (or have it as a file static or, perish the thought, global variable).
Note that this code does not return a value, but it can be used anywhere in a function that a void expression could be used:
if (somefunc() != 0)
DISPLAY_ERR();
else if (anotherfunc() != 0)
DISPLAY_ERR();
else
do_something_useful_after_all();
Etc.
I would still want to make sure I measured the overhead of using a regular function versus having the function-like macro. Used often enough, you might be still be better off with a real function.

Resources