Evaluate macro parameter once only - c

In the following code, whatever is passed as retval is evaluated as given for every use of that token.
#define _CPFS_RETURN(commit, retval) do { \
util_cpfs_exit(commit); \
return retval; \
} while (false)
#define CPFS_RETURN_BOOL(retval) do { \
_CPFS_RETURN(retval, retval); \
} while (false)
For example given the use CPFS_RETURN_BOOL(inode && file_truncate(inode, len));, this is generated:
do {
do {
util_cpfs_exit(inode && file_truncate(inode, len));
return inode && file_truncate(inode, len);
} while (0);
} while (0);
Evidently I don't want to execute the statement inode && file_truncate(inode, len); more than once.
How can I ensure that the given tokens are evaluated before being pasted helter-skelter?
Update
I believe I have good reason to use macros here. Where possible, code is put into real functions (such as util_cpfs_exit) which are invoked from a set of macros I'm using. The macros vary based on the return type: in C++ I'd have explicit templates to handle this.

As your macro vary on the return type, you can evaluate the retval expression and store it in a variable of the right type inside the first level of macro then use this variable. ie:
#define CPFS_RETURN_BOOL(retval) do { \
bool _tmp_ = retval;
_CPFS_RETURN(_tmp_, _tmp_); \
} while (false);
If I understand well, that should be enough for your use case, and for other use cases you can use functions.
In your exemple you'll get:
do {
bool _tmp_ = inode && file_truncate(inode, len);
do {
util_cpfs_exit(_tmp_);
return _tmp_;
} while (0);
} while (0);
Looks fine.
PS: as a sidenote if you always use _CPFS_RETURN indirectly through another macro following the above model, there is no need to protect it by a do { } while (false);. Also, putting a semi-colon after the while(false) removes most of the interest of using it... that may be a good example of why C macros are dangerous and hides easy pitfalls. Not that I dislike macros, quite the contrary. I'm from the (probably rare) kind of people that would prefer C macros to be enhanced to bypass their current limitations to become really cool (and no, C++ templates are not enhanced macros, they are something completely different).

I would recommend that you evaluate the condition first.
i.e.
bool val = inode && file_truncate(inode, len);
Other than that may advice would be to steer well clear of macros, they seem unnecessary in this instance, use functions instead.

Write a function instead of using a macro. In this case, where you want to build a return statement in, you might be better off just writing the code explicitly instead of relying on a macro to hide what you're doing.

Change the macro to a "static inline" function. In gcc, it's as fast as a macro.
http://gcc.gnu.org/onlinedocs/gcc/Inline.html

Related

How to implement Go's defer() in C so that it allows declaring vars?

In this Modern C video there's a trick that allows to postpone execution of a code until the block/scope exits. It's used as follows:
int main()
{
int foo=0, bar;
const char *etc = "Some code before defer";
defer(profile_begin(), profile_end())
{
/* Some code, which will be automatically
* preceded by call to profile_begin() and
* followed by run of profile_end().*/
foo++;
bar = 1;
}
etc = "Some code after defer";
foo = bar + 1;
}
Implementation from the video:
#define macro_var_line(name) concat(name, __LINE__)
#define defer(start,end) for( \
int macro_var_line(done) = (start,0); \
!macro_var_line(done); \
(macro_var_line(done) += 1), end)
It's pretty simply implemented. What might be confusing is the macro_var_line(name) macro. Its purpose is to simply ensure that a temporary variable will have a unique, "obfuscated" name by adding current line number to it (of where defer is called).
However the problem is that one cannot pass code to start snippet that declares new variables, because it is pasted in the for() comma operator that uses int type (the int macro_var_line(done) = …). So it's not possible to, eg.:
defer(FILE *f = fopen("log.txt","a+"), fclose(f))
{
fprintf(f,"Some message, f=%p",f);
}
I would want to have such macro, capable of declaring new vars in start snippet. Is it achievable with standard C99, C11 or maybe some GCC extensions?
UPDATE: I've found a solution utilizing GCC nested functions. Basically, the { bblock } that's following the defer() macro becomes nested function body. And it's possible to forward declare the nested function and invoke it from before the block, i.e.:
#define defer(start,end) \
auto void var_line(routine) (void); \
start; \
/* Invoke above predeclared void routine_123(void) function */ \
var_line(routine)(); \
end; \
/* Define the nested function */ \
void var_line(routine) (void)
UPDATE2: Here's an elegant version which:
runs first leading statements as start and the last one as the end code,
runs the very first statement in its own for()/declarative space,
runs the block properly via an if(cond == 0) check/block start up.
#define defer(...) \
for (int var_line(cond) = 0; var_line(cond) == 0; ) \
for (FIRST_ARG(__VA_ARGS__); var_line(cond) == 0; ) \
for (SKIP_LAST_ARG(SKIP_FIRST_ARG(__VA_ARGS__)); \
var_line(cond) == 0; \
var_line(cond) += 1 ) \
for (int var_line(cond_int) = 0; \
var_line(cond_int) <= 1; \
var_line(cond_int) += 1 ) \
if (var_line(cond_int) == 1) \
{ \
LAST_ARG(__VA_ARGS__); \
} else if (var_line(cond_int) == 0)
As I expressed in comments, my recommendation is to avoid using such a thing in the first place. Whatever your video might have said or implied, the prevailing opinion among modern C programmers is that macro usage should be minimized. Variable-like macros should generally represent context-independent constant values, and function-like macros are usually better implemented as actual functions. That's not to say that all macro use must be avoided, but most modern C professionals look poorly on complex macros, and your defer() is complex enough to qualify.
Additionally, you do yourself no favors by trying to import the style and idioms of other languages into C. The common idioms of each language become established because they work well for that language, not, generally, because they have inherent intrinsic value. I advise you to learn C and the idioms that C programmers use, as opposed to how to write C code that looks like Go.
With that said, let's consider your defer() macro. You write,
However the problem is that one cannot pass code to start snippet that declares new variables
, but in fact the restriction is stronger than that. Because the macro uses the start argument in a comma expression (start,0), it needs to be an expression itself. Declarations or complete statements of any kind are not allowed. That's only indirectly related to that expression appearing in the first clause of a for statement's control block. (The same applies to the end argument, too.)
It may also be important to note that the macro expands to code that fails evaluate the end expression if execution of the associated statement terminates by branching out of the block via a return or goto statement, or by executing a function that does not return, such as exit() or longjmp(). Additionally, unlike with Go's defer, the end expression is evaluated in full after the provided statement -- no part of it is evaluated before, which might surprise a Go programmer. These are characteristics of the options presented below, too.
If you want to pass only the start and end as macro arguments, and you want to allow declarations to appear in start, then you could do this:
// Option 1
#define defer(start,end) start; for( \
int macro_var_line(done) = 0; \
!done; \
(macro_var_line(done) += 1), (end))
That moves start out of the for statement in the macro's replacement text, to a position where arbitrary C code may appear. Do note, however, that any variable declarations will then be scoped to the innermost containing block.
If you want to limit the scope of your declarations then there is also this alternative and variations on it, which I find much more straightforward than the original:
// Option 2
#define defer(start, end, body) { start; body end; }
You would use that like so:
defer(FILE *f = fopen("log.txt","a+"), fclose(f), // argument list continues ...
fprintf(f,"Some message, f=%p",f);
);
That is somewhat tuned to your particular example, in that it assumes that the body is given as a sequence of zero or more complete statements (which can include blocks, flow-control statements, etc). As you can see, it also requires the body to be passed as a macro argument instead of appearing after the macro invocation, but I consider that an advantage, because it facilitates recognizing the point where the deferred code kicks in.
You can simulate defer by using the __attribute__((cleanup(...))) feature of GCC and Clang. Also see this SO question about freeing a variable.
For instance:
// the following are some utility functions and macros
#define defer(fn) __attribute__((cleanup(fn)))
void cleanup_free(void* p) {
free(*((void**) p));
}
#define defer_free defer(cleanup_free)
void cleanup_file(FILE** fp) {
if (*fp == NULL) { return; }
fclose(*fp);
}
#define defer_file defer(cleanup_file)
// here's our code:
void foo(void) {
// here's some memory allocation
defer_free int* arr = malloc(sizeof(int) * 10);
if (arr == NULL) { return; }
// some file opening
defer_file FILE* fp1 = fopen("file1.txt", "rb");
if (fp1 == NULL) { return; }
// other file opening
defer_file FILE* fp2 = fopen("file2.txt", "rb");
if (fp2 == NULL) { return; }
// rest of the code
}
There is actually an effort in the standard's committee to standardize a defer feature. The paper proposal also comes with a reference implementation. The idea is to propose such a feature that may be implemented with the least compiler magic possible.
If all goes to plan, that feature could even be rebase on lambdas, if we get these into C23 in time.
You could use a trick from "Smart Template Container for C". See link.
#define c_autovar(declvar, ...) for (declvar, *_c_ii = NULL; !_c_ii; ++_c_ii, __VA_ARGS__)
Basically you declare a variable and hijack it's type to form a NULL pointer. This pointer is used as a guard to ensure that the loop is executed only once.
Incrementing NULL pointer is likely Undefined Behavior because the standard only allows to form a pointer pointing just after an object and NULL points to no object. However, it's likely run everywhere.
I guess you could get rid of UB by adding a global variable:
int defer_guard;
And setting the guard pointer to a pointer to defer_guard in the increment statement.
extern int defer_guard;
#define defer_var(declvar, cleanup) \
for (declvar, *_c_ii = NULL; \
!_c_ii; \
_c_ii = (void*)&defer_guard, cleanup)
It will work fine when invoked as:
defer_var(FILE *f = fopen("log.txt","a+"), fclose(f))
{
fprintf(f,"Some message, f=%p",f);
}
EDIT
Actually it is possible to derive a macro that will accept both expression and declaration as start. One must use two for loops instead of one.
#define DEFER(start, end) \
for (int _done = 0; !_done;) \
for (start; !(_done++); end)
int main() {
DEFER(FILE *f = fopen("log.txt","a+"), fclose(f)) {
fprintf(f,"Some message, f=%p", (void*)f);
}
FILE *f;
DEFER(f = fopen("log.txt","a+"), fclose(f)) {
fprintf(f,"Some message, f=%p", (void*)f);
}
return 0;
}

Linux Kernel defines everywhere

On linux's kernel we can find this piece of code in linux/sched.h, when I saw it some doubts came to my mind:
Why using define to create functions? Why not using the normal return-type function-name(par1, par2) {} style?
What is the point with the do {} while(0)?
#define set_special_state(state_value)
do {
unsigned long flags;
raw_spin_lock_irqsave(&current->pi_lock, flags);
current->state = (state_value);
raw_spin_unlock_irqrestore(&current->pi_lock, flags);
} while (0)
#endif
This isn't a "function", it's a preprocessor macro.
Sometimes one must use macros to do things that the C language itself doesn't support (usually generating code). This doesn't look like one of those cases though, and should probably be a static inline function. Pergaps the Git history would explain why it is the way it is.
do { ... } while (0) is a common method for swallowing the semicolon which follows a call to a C-function-looking macro like this one.
Functions are usually preferrable because they provide type checking and aren't error prone to things like double evaluation, but macros are more powerful, since they allow you to work at the text/token level.
do{}while(0) is to make an invoked macro grammatically behave like a void-returning function call.
You might think a plain pair of curlies would do that but that doesn't work
with if-else
#define macro_with_curlies() { }
if(x) macro_with_curlies(); else { }
//expands to: if(x) { }; /*else is illegal after the semicolon*/ else { }

Purpose of #define foo() do { } while (0)

While browsing sources of LinCAN driver, I found some macros that baffled me.
#else /*CONFIG_PREEMPT*/
#define can_preempt_disable() do { } while (0)
#define can_preempt_enable() do { } while (0)
#endif /*CONFIG_PREEMPT*/
I understand the usefulness of
do {
...;
if(condition) break;
...
} while (0);
using break as a kind of throw. I semi-understand wrapping a sequence of functions like
#define FOO() do { foo(); bar(); } while (0)
to avoid caveats with braceless if. I understand sometimes "no-op statements" are required for a #define. But why this particular kind? specifically, empty braces, false condition, do...while? Some syntax caveats I can't quite grasp?
It is a common syntax for notifying the compiler that macro should be treated as a statement instead of as an expression (statements vs expressions).
In this case compiler will alert you if you try to use can_preempt_disable() as an expression. This means that we forced compile-time check that can_preempt_disable() is used as a statement. Compile-time checks are very often desirable.
The complete passage from the relevant file is:
#if !defined(CONFIG_PREEMPT_RT) && ( defined(CONFIG_PREEMPT) ||
(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) )
#define can_preempt_disable preempt_disable
#define can_preempt_enable preempt_enable
#else /*CONFIG_PREEMPT*/
#define can_preempt_disable() do { } while (0)
#define can_preempt_enable() do { } while (0)
#endif /*CONFIG_PREEMPT*/
Thus, the first part is the code you get when you've asked for pre-emption protection, otherwise you get the empty, do-nothing, loops.
I guess they're written like that for the usual reasons, i.e. to ensure that the macro still is a valid statement.
There shouldn't be a terminating semicolon in the definition, since that will be in the code using these, such as this function which begins:
int c_can_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj)
{
can_preempt_disable();
...
So, clearly the macro is used like any other function call, and the semicolon is right there where the macro is invoked. This is very normal.
UPDATE 2: Defining it to a ; leads to double semicolons which is ugly, at least in my opinion. An empty brace pair {} would work I guess, but this do/while construct is even more idiomatic since it's often used in cases like these.
UPDATE 3: As pointed out in a comment, an empty brace pair won't work since then you can't put a semicolon after the call. Aah. Thanks!

Is it OK to use a code block as an argument for a C macro?

I have a pattern that is basically some boilerplate code with a part that varies in the middle
if(condition){
struct Foo m = start_stuff();
{ m.foo = bar(1,2); m.baz = 17; } //this part varies
end_stuff();
}
Is it OK to make a macro taht takes that intermediate code block as an argument? The rules for macro expansion in C seem awfully complicated so I am not sure if there aren't any corner cases that could come and bite me in the future (in particular, I don't understand how the macro arguments are separated if my code has commas in it).
#define MY_MACRO(typ, do_stuff) do { \
if(condition){ \
struct typ m = start_stuff(); \
do_stuff; \
end_stuff(); \
} \
}while(0)
//usage
MY_MACRO(Foo, {
m.foo = bar(1,2);
m.baz = 17;
});
So far the only thing that I managed to think of is break and continue getting captured if I use looping statements in my macro and that would be an acceptable tradeoff for my particular use case.
edit: Of course, I would have used a functions if I could. The example I used in this question is simplified and doesn't showcase the bits that can only work with macro magic.
You can put a code block into a macro argument provided that it has no unguarded comma. In your example, the only comma in the argument is guarded because it is surrounded by parentheses.
Note that only parentheses guard commas. Brackets ([]) and braces ({}) do not. (And neither do angle brackets (<>) as noted in a comment.)
However, if the code block argument is the macro's last argument, you can use a variadic macro to increase flexibility. But beware: the increased flexibility also means that errors might go unnoticed. If you do this, you'll only have to make sure that the parentheses are balanced. (Again, only parentheses matter to the macro processor.)
As an alternative, you could consider using a macro that precedes your compound statement, as illustrated below. One of the pros of this is that all debuggers would still be able to step inside your compound statement, which is not the case with the compound-statement-as-macro-argument method.
//usage
MY_MACRO(Foo, condition) {
m.foo = bar(1,2);
m.baz = 17;
}
Using some goto magic (yes, 'goto' may be evil in some cases, but we have few alternatives in C), the macro can be implemented as:
#define CAT(prefix, suffix) prefix ## suffix
#define _UNIQUE_LABEL(prefix, suffix) CAT(prefix, suffix)
#define UNIQUE_LABEL(prefix) _UNIQUE_LABEL(prefix, __LINE__)
#define MY_MACRO(typ, condition) if (condition) { \
struct typ m = start_stuff(); goto UNIQUE_LABEL(enter);} \
if (condition) while(1) if (1) {end_stuff(); break;} \
else UNIQUE_LABEL(enter):
Note that this has a small performance and footprint impact when compiler optimization is disabled. Also, a debugger will seem jump back to the MY_MACRO line when running calling the end_stuff() function, which is not really desirable.
Also, you might want to use the macro inside a new block scope to avoid pollution your scope with the 'm' variable:
{MY_MACRO(Foo, condition) {
m.foo = bar(1,2);
m.baz = 17;
}}
Of course, using 'break' not inside a nested loop in the compound statement would skip the 'end_stuff()'. To allow for those to break the surrounding loop and still call 'end_stuff()', I think you'd have to enclose the compound statement with a start token and an end token as in:
#define MY_MACRO_START(typ, condition) if (condition) { \
struct typ m = start_stuff(); do {
#define MY_MACRO_EXIT goto UNIQUE_LABEL(done);} while (0); \
end_stuff(); break; \
UNIQUE_LABEL(done): end_stuff();}
MY_MACRO_START(foo, condition) {
m.foo = bar(1,2);
m.baz = 17;
} MY_MACRO_END
Note that because of the 'break' in that approach, the MY_MACRO_EXIT macro would only be usable inside a loop or switch. You could use a simpler implementation when not inside a loop:
#define MY_MACRO_EXIT_NOLOOP } while (0); end_stuff();}
I used 'condition' as a macro argument, but you may also embed it directly in the macro if desired.
You can put code block into a macro but you must be warned that it makes debugging a lot harder using a debugger. IMHO is better just to either write a function or cut'n'paste the lines of code.
How about function pointers instead (and optionally inline functions)?
void do_stuff_inner_alpha(struct Foo *m)
{
m->foo = bar(1,2); m->baz = 17;
}
void do_stuff_inner_beta(struct Foo *m)
{
m->foo = bar(9, 13); m->baz = 445;
}
typedef void(*specific_modifier_t)(struct Foo *);
void do_stuff(specific_modifier_t func)
{
if (condition){
struct Foo m = start_stuff();
func(&m); //this part varies
end_stuff();
}
}
int main(int argc, const char *argv[])
{
do_stuff(do_stuff_inner_beta);
return EXIT_SUCCESS;
}
"Is it OK?" may mean two things:
Will it work? Here the answer is generally yes, but there are pitfalls. One, as rici mentioned, is an unguarded comma. Basically, remember that macro expansion is a copy&paste operation, and the preprocessor doesn't understand the code it copies and pastes.
Is it a good idea? I'd say the answer is generally no. It makes your code unreadable and hard to maintain. In some rare cases, this may be better than alternatives, if implemented well, but that's the exception.
Note that in C++ you could use a lambda the following way:
#include <iostream>
#define MY_MACRO(body) \
setup();\
body();\
teardown();\
int main() {
int a = 1;
MY_MACRO(([&]() mutable {
std::cout << "Look, no setup" << std::endl;
a++;
}));
std::cout << "a is now " << a << std::endl;
}
If you do this, you should first consider if there should instead be a function that plainly takes the lambda:
void withSetup(std::function<void ()> callback) {
setup();
callback();
teardown();
}
int main() {
withSetup([&]() {
doStuff();
});
}
Before answering your question "is it OK to use macro" I'd like to know why you want to convert that block of code to macro. What's that you're trying to gain and at what cost?
If same block of code you're using repeatedly, it's better to convert that in a function, maybe an inline function and leave it to compiler to make it inline or not.
Should you run into crash\issue, debugging a macro is a tedious task.

Scope Guard in C

I would like to use scope guard in C in order to do profiling.
I would like to know how much time I spend in a function. Here is what I do:
int function() {
tic();
... do stuff ...
if (something)
{
toc();
return 0;
}
toc();
return 1;
}
I need to place a toc statement each time I exit the function. I would like to do that without having to copy paste toc everywhere. Is there a generic way to do that, using a macro or something ?
Also I don't want to change the way the function is called, as there are many functions I have to profile.
Thanks
This doesn't change the way the function is called. Probably not much use if you want to be able to profile every single function, though.
static inline int real_function() {
// previous contents of function(), with no tic or toc
}
int function() {
tic();
int r = real_function();
toc();
return r;
}
As everyone else says: use a profiler, it will save you a lot of effort in the long run. As they don't say: if your platform has one.
If it doesn't, then the easiest might be to say (as a coding rule) that functions must have only one exit point, and that exit point must be via your macro. Then you can manually instrument all your functions with code at entry and exit. Legacy functions with multiple returns can be wrapped up as above.
Also, bear in mind when you're doing anything like this that your compiler can mess you up. You might write this:
tic();
do_something();
int i = something_else();
toc();
return i;
If the compiler determines that something_else has no side-effects, then even though something_else takes significant time, it might turn the code into this:
tic();
do_something();
toc();
return something_else();
And your profile data will under-estimate the time spent in your function. Another reason it's so good to have a real profiler - it can co-operate with the compiler.
You could define a macro like:
#define TOC_RETURN(x) \
do { \
toc(); \
return x; \
} while(0)
which should work anywhere you put it. Then you can automate replacing return *; with TOC_RETURN(*).
Why not use an actual profiling tool, like gprof?
You could just "redefine" return via a macro: (please see Disclaimer)
#include <stdio.h>
void tic() { printf("tic\n"); }
void toc() { printf("toc\n"; }
#define return toc(); return
int foo() {
tic();
return 0;
}
#undef return
int main() {
foo();
return 0;
}
Disclaimer: This can be considered ugly and hacky because:
It won't work for void functions unless you use return;-statements.
It might not be portable/standard, even though it works on MSVC8.
One shouldn't define keywords.
I am very late to the party, but there is another way to do scope guarding in C using the GCC extension cleanup attribute. The cleanup attribute attaches a function to a variable declaration that is run when the variable goes out of scope. Originally intended to perform memory deallocation for dynamically allocated types, it can also be abused as a scope guard.
void cleanup_toc(int *ignored __attribute__((__unused__))) { toc(); }
int function(void) {
tic();
int atexit __attribute__((__cleanup__(cleanup_toc))) = 0;
//... do stuff ...
if (something) {
return 0;
}
return 1;
}
This solution does not use macros, but you can of course wrap this into a macro. For example:
#define CONCATENATE_IMPL(x, y) x ## y
#define CONCATENATE(x, y) CONCATENATE_IMPL(x, y)
#define ATEXIT(f) int CONCATENATE(atexit, __LINE__) __attribute__((__cleanup__(f))) = 0
int function(void) {
ATEXIT(cleanup1); // These are executed in reverse order, i.e.
ATEXIT(cleanup2); // cleanup2 will run before cleanup1.
}
I wouldn't recommend a macro for this. You profile the code just once in a while, and replacing 'return' with some special macro just for that purpose makes code less readable.
Isn't it better to do as follows?
tic();
call_function();
toc();
This automatically handles "all exit points" from the function.
P.S. Why don't you use a profiler?
A real profiler doesn't need you to modify the code, just to compile it with profiling enabled.
Hmm, maybe wrap the function call in a macro (family of macros, really)? Here is one which takes no arguments and returns Retval:
// define the wrapper for name
#define DEFTIMECALL0(Retval,name) \
Retval timed##name() \
{ \
Retval ret;
tic(); \
ret = name(); \
toc(); \
return ret; \
}
You'll need macros for every arity of function calls you make, with a Retval and void returning version.
Edit Maybe there isn't even a point in defining the wrapper function, and better to just have a family of macros (again, for each arity and return type/void versions) which wrap a function call in a tic/toc directly at the callsites
Don't be afraid of instrumenting profilers, which essentially do this for you.

Resources