Is the practice of defining a macro returning a value for a function?

Using a macro defined to conditionally return a value has the disadvantage of not being able to see that only viewing the client code can exit at the macro point.

The use case that I am considering writes value and error checking, for example:

#define WRITE_CHK(file, param)\ if (!write_that_returns_zero_on_fail(file, param)) {\ handle_error();\ return false;\ } 

client code:

 bool myfunc() { ... WRITE_CHK(file, param) // function might return here ... return true; } 

I am wondering if the advantages of the macro (which will be used in many places in my code) outweigh the disadvantage mentioned above. Are there any preferred alternatives besides just extending (without using a macro)?

+6
source share
4 answers

The standard answer is "do not use macros"; but this is often a bit simplistic. Sometimes there are times when they can significantly reduce the number of parts that you would otherwise have.

So why not code this fact in the name of the macro? e.g. WRITE_OR_RETURN_ON_FAILURE . This may be a bit verbose, but much less likely to disable readers of your code.

+14
source

Hiding the control flow inside a macro is not used very often, so it can confuse developers who have to understand or debug your code.

I would recommend not using macros fully, but if you need to use them, make sure that part of the control flow is explicit.

 // assume handle_error returns true #define WRITE_FAILED(file, param)\ (!write_that_returns_zero_on_fail(file, param) && handle_error()) // macro usage if(WRITE_FAILED(file, param)) { return; } 

Another question to ask yourself is why do you want to use macros anyway? If it were to hide the flow of control, then this is not a good idea. Is there any other reason?

+2
source

Make a two-step macro:

 #define WRITE_CHK_(file, param, HANDLER)\ if (!write_that_returns_zero_on_fail(file, param)) {\ handle_error();\ HANDLER\ } #define RFALSE return false; #define WRITE_CHK(file, param) WRITE_CHK_(file, param, RFALSE) 

Then you can do other wrappers if you need a similar check elsewhere (or use WRITE_CHK(file, param, return false) )

+1
source

Yes this is bad. Use goto .

  #define fail_unless(x) do {if(!(x)) goto fail;} while (0) int foo() { fail_unless( my_write(...) ); fail_unless( bar() ); return 0; fail: cleanup(); return -1; } 

Edit : if you are understated because you donโ€™t understand what the while loop is doing there, you should just ask. This is the standard method for ensuring that the C macro acts as a single statement in any context. If your macro expands to an if statement (for example, macros in another, pending answers), you get unexpected side effects, for example:

  #define DONT_DO_THIS(x) if (!x) { foo; } if (a) DONT_DO_THIS(x) else something_else(); 

It was expected that something_else would execute when !a , but what the macro actually expands is:

  if (a) if (!x) { foo;} else something_else(); 

And something_else is executed when a && x , and not when !a , as the programmer planned.

-4
source

Source: https://habr.com/ru/post/894685/


All Articles