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.
Related
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.
I am working on a heavily resource-constrained embedded platform.
I want a macro that will capture function call errors and log them to a fixed-size buffer.
My wish is to be able to do something like
returnType retval;
CAPTURE_ERRORS(retval, function_name, argument1, moreArgsMaybe);
if (retval) { other_error_handling(); }
Where
#define N 12
#define CAPTURE_ERRORS(retval, func, ...) \
do { retval = func(__VA_ARGS__); \
if (retval!=0) write_log_entry(#func[0:N],(int)retval); \
} while (0)
Obviously, the Python slice syntax won't work. Is there any way to get the first N characters of a stringized macro argument?
(I don't want to do the truncation inside write_log_entry, because then the whole long function name will be stored in the executable image, only to be thrown away later.)
I am not aware of any way as a string. (Somebody who is aware, please enlighten me!)
Edit The easiest way I know is to make all your function names no more than N characters long! Think of all that Fortran code with N=6. :)
The second easiest way I know is to pass an additional parameter to CAPTURE_ERRORS:
#define N 12
/* vvvv */
#define CAPTURE_ERRORS(retval, func, tag, ...) \
do { retval = func(__VA_ARGS__); \
if (!retval) write_log_entry(#tag,(int)retval); \
} while (0) /* ^^^^ */
and
CAPTURE_ERRORS(retval, function_name, function_nam, argument1, moreArgsMaybe);
^^^^^^^^^^^^
This is a sufficiently restricted form that you could automatically stuff tag in your existing CAPTURE_ERRORS call with a Python (or even sed!) script that you run before compiling.
Edit
A discussion thread coming to the same conclusion — use an external tool.
In C++, you could likely do this at compile time with a template. :) Not unlike this question, but stopping at length N.
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();.
I would like to force a functions parameters to accept only specific definitions. For example, consider #define OUTPUT 1, #define INPUT 0 and void restrictedFunction(int parameter); .
How would I force restrictedFunction(int parameter) to accept only OUTPUT or INPUT?
I would also like to take into consideration that another definition may have the same value, for example, #define LEFT 1 and #define RIGHT 0.
So in this case I would like restrictedFunction(int parameter) to be able to accept only OUTPUT and INPUT specifically.
typedef enum { INPUT = 0, OUTPUT = 1 } IO_Type;
void restrictedFunction(IO_Type parameter) { ... }
It doesn't absolutely force the use of the values (the compiler will let someone write restrictedFunction(4)), but it is about as good as you'll get.
If you truly want to force the correct type, then:
typedef enum { INPUT = 0, OUTPUT = 1 } IO_Type;
typedef struct { IO_Type io_type } IO_Param;
void restrictedFunction(IO_Param parameter) { ... }
In C99 or later, you could call that with:
restrictedFunction((IO_Param){ INPUT });
This is a compound literal, creating a structure on the fly. It is not entirely clear that the structure type really buys you very much, but it will force the users to think a little and may improve the diagnostics from the compiler when they use it wrong (but they can probably use restrictedFunction((IO_Param){ 4 }); still).
What this means is that your restrictedFunction() code should be ready to validate the argument:
void restrictedFunction(IO_Type io_type)
{
switch (io_type)
{
case INPUT:
...do input handling...
break;
case OUTPUT:
...do output handling...
break;
default:
assert(io_type != INPUT && io_type != OUTPUT);
...or other error handling...
break;
}
}
You could use an enum.
typedef enum TrafficDirection { INPUT = 0, OUTPUT = 1 } TrafficDirection;
restrictedFunction(TrafficDirection direction);
of course, this isn't perfect. You can still pass any int to it as long as you use a cast.
restrictedFunction((TrafficDirection) 4);
You don't get quite as much protection as you might like, but you can do:
enum func_type { INPUT, OUTPUT };
void restrictedFunction( enum func_type parameter );
You can use a wrapper to validate the argument:
#define restrictedFunction(x) do { \
static_assert((x) == INPUT || (x) == OUTPUT); \
assert(!strcmp(#x, "INPUT") || !strcmp(#x, "OUTPUT")); \
restrictedFunction(x); \
} while(0)
Notes:
This assumes restrictedFunction() returns a void. If it returns a value which you actually use, you'll need something like gcc's compound statement http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html. Or--better--you can use BUILD_BUG_ON_ZERO (see What is ":-!!" in C code?), which I keep forgetting about, because it doesn't seem to work with C++.
The do ... while(0) is to "swallow the semi-colon"; not really relevant here.
static_assert() is a compile-time assert; there are many variants available. Here is a link to one, https://stackoverflow.com/a/9059896/318716, if you don't have your own handy.
assert() is the standard run-time assert.
With gcc 4.1.2, and my version of static_assert(), you can replace the run-time assert() with a compile-time assert when the two !strcmp()'s are replaced with ==; see example below. I haven't tested this with other compilers.
x is only used once in the macro expansion, since the first four references are only used at compile-time.
When your actually define your function, you'll have to add parentheses to disable the macro expansion, as in:
void (restrictedFunction)(int x){ ... }
Also, if your code has a special case (whose code doesn't?) where you need to call restrictedFunction() with the argument foo, you'll need to write:
(restrictedFunction)(foo);
Here is a complete example, which puts a wrapper around the standard library function exit():
#include <stdlib.h>
#define CONCAT_TOKENS(a, b) a ## b
#define EXPAND_THEN_CONCAT(a,b) CONCAT_TOKENS(a, b)
#define ASSERT(e) enum{EXPAND_THEN_CONCAT(ASSERT_line_,__LINE__) = 1/!!(e)}
#define ASSERTM(e,m) enum{EXPAND_THEN_CONCAT(m##_ASSERT_line_,__LINE__)=1/!!(e)}
#define exit(x) do { \
ASSERTM((x) == EXIT_SUCCESS || (x) == EXIT_FAILURE, value); \
ASSERTM(#x == "EXIT_SUCCESS" || #x == "EXIT_FAILURE", symbol); \
exit(x); \
} while(0)
int main(void) {
exit(EXIT_SUCCESS); // good
exit(EXIT_FAILURE); // good
exit(0); // bad
exit(3); // doubly bad
}
If I try to compile it, I get:
gcc foo.c -o foo
foo.c: In function 'main':
foo.c:17: error: enumerator value for 'symbol_ASSERT_line_17' is not an integer constant
foo.c:18: warning: division by zero
foo.c:18: error: enumerator value for 'value_ASSERT_line_18' is not an integer constant
foo.c:18: error: enumerator value for 'symbol_ASSERT_line_18' is not an integer constant
instead of checking every input pointer argument with if condition if( in != NULL ), is there better way to do this. One method is to create some macros, like
#define CHECK_ARG(x) if(!(x)) { return 0; }
In code it's look like this
int some_func( int * first_arg, int * second_arg )
{
CHECK_ARG( first_arg );
CHECK_ARG( second_arg );
// some operations
//
}
In my opinion this is good approach, but before adding this, I want to know is there any better ways doing this?
Thanks in advance!
I would use some ASSERT in there instead - at least in your debug version.
Also, what George said - its not readable and clear that it returns 0.
Macros are usually frowned upon, but sometimes extermely useful. But macros that have "hidden" side effects (like returning) are potentially dangerous, because they're difficult to spot. At least consider renaming your macro to make this explicit, e.g. CHECK_ARG_AND_RETURN_IF_INVALID. It's verbose, but it's hard to miss.
In your function write
assert_or_return(first_arg != NULL);
assert_or_return(second_arg != NULL);
Define assert_or_return so that in the debug version it will fire up the debugger (by calling abort), and in the release version it will log the error and return (as you want to do). I assume you're confident that returning from the function when one of the arguments is NULL will do more good than harm in the production version of your application. If by returning early you will irrevocably corrupt your users' data or cause a furnace to explode, it would be better to terminate early, perhaps with a custom error message.
The following example illustrates how your idea can be implemented.
#ifdef NDEBUG
#define assert_or_return(expr) do { \
if (!(expr)) { \
fprintf(logfile, "Assertion %s in %s(%d) failed\n", #expr, __FILE__, __LINE__); \
return 0; \
} \
} while(0)
#else
#define assert_or_return(expr) do { \
if (!(expr)) { \
fprintf(stderr, "Assertion %s in %s(%d) failed\n", #expr, __FILE__, __LINE__); \
abort(); \
} \
} while(0)
#endif
Maybe you can assertions. Have a look at assert.h.