Disable multiline statements with c/c++ macro - c++

Is it possible to disable chunks of code with c/c++ preprocessor depending on some definition, without instrumenting code with #ifdef #endif?
// if ENABLE_TEST_SONAR is not defined, test code will be eliminated by preprocessor
TEST_BEGIN(SONAR)
uint8_t sonar_range = get_sonar_measurement(i);
TEST_ASSERT(sonar_range < 300)
TEST_ASSERT(sonar_range > 100)
TEST_END
Functionally equivalent to something as follows:
#ifdef TEST_SONAR
serial_print("test_case sonar:\r\n");
uint8_t sonar_range = get_sonar_measurement(i);
serial_print(" test sonar_range < 300:%d\r\n", sonar_range < 300);
serial_print(" test sonar_range > 100:%d\r\n", sonar_range > 100);
#endif TEST_SONAR

Multiple lines can be disabled only with #ifdef or #if but single lines can be disabled with a macro. Note that multiple lines can be combined with \
#ifdef DOIT
#define MYMACRO(x) \
some code \
more code \
even more \
#else
#define MYMACRO(x)
#endif
Then when you call MYMACRO anplace that code will either be included or not based on whether DOIT is defined
That's the closest you can come and is used frequently for debugging code
EDIT: On a whim I tried the following and it seems to work (in MSVC++ and g++):
#define DOIT
#ifdef DOIT
#define MYMACRO(x) x
#else
#define MYMACRO(x)
#endif
void foo(int, int, int)
{
}
int main(int, char **)
{
int x = 7;
MYMACRO(
if (x)
return 27;
for (int i = 0; i < 10; ++i)
foo(1, 2, 3);
)
}

No, the only way to disable sections of codes effectively using preprocessing is by #ifdef #endif. Theoretically, you could use #if identifier, but it's better to stick to checking whether a variable is defined.
Another option (perhaps) is to use a preprocessing macro:
Edit:
Perhaps using plain functions and #ifdef might work better?
function test_function() {
/* Do whatever test */
}
#define TESTING_IDENTIFIER
#define TEST( i, f ) if ((i)) do { f } while (0)
Then, for each test, you define a unique identifier and call it by providing the identifier first and the function (with parenthesis) second.
TEST( TESTING_IDENTIFIER, test_function() );
Finally, f can be anything that's syntactically correct -- You don't have to create a function for every test, you can put the code inline.

I will anyway mention an obvious solution of
#define DO_TEST_SONAR
#ifdef DO_TEST_SONAR
#define TEST_SONAR if(true) {
#else
#define TEST_SONAR if(false) {
#endif
#define TEST_SONAR_END }
...
TEST_SONAR
code
TEST_SONAR_END
The code will still get compiled, not completely removed, but some smart compilers might optimize it out.
UPD: just tested and
#include <iostream>
using namespace std;
//#define DO_TEST_SONAR
#ifdef DO_TEST_SONAR
#define TEST_SONAR if(true) {
#else
#define TEST_SONAR if(false) {
#endif
#define TEST_SONAR_END }
int main() {
TEST_SONAR
cout << "abc" << endl;
TEST_SONAR_END
}
produces absolutely identical binaries with cout line commented out and non commented, so indeed the code is stripped. Using g++ 4.9.2 with -O2.

Related

Defined() operator not recognized by the compiler when used with the ## operator

My purpose is to have a macro that returns a pointer to a variable (&LPUART(id)_handle) that might or might not be declared, in the latter case the pointer should be a nullptr
#define NUMBER_OF_UARTS defined(LPUART1_PERIPHERAL)+defined(LPUART2_PERIPHERAL)
#define GET_UART_HANDLE_POINTER(id) defined(LPUART##id##_PERIPHERAL)?&LPUART##id##_handle:nullptr
Problem is that the compiler throws
error: 'defined' was not declared in this scope
this while the defined() operator is used successfully with the macro NUMBER_OF_UARTS.
I can achieve the desired result omitting defined()
#define GET_UART_HANDLE_POINTER(id) (LPUART##id##_PERIPHERAL)?&LPUART##id##_handle:nullptr
However I was wondering why defined does not work in the first example.
Ide: MCUXpresso IDE v11.3.0 [Build 5222] [2021-01-11]
Toolchain NXP MCU Tools
Language C++
Target Arm
The preprocessor does not know anything about C and it will do the ternary operations. Also defined() cannot be used in this context.
To achieve this using only the preprocessor, a bit more typing is needed:
#define LPUART1_PERIPHERAL ((void *)0x4567800)
#if defined(LPUART1_PERIPHERAL)
#define LPUART1_DEF 1
#define LPUART1_HND LPUART1_PERIPHERAL
#else
#define LPUART1_DEF 0
#define LPUART1_HND nullptr
#endif
#if defined(LPUART2_PERIPHERAL)
#define LPUART2_DEF 1
#define LPUART2_HND LPUART2_PERIPHERAL
#else
#define LPUART2_DEF 0
#define LPUART2_HND nullptr
#endif
#define NUMBER_OF_UARTS (LPUART1_DEF + LPUART2_DEF)
#define GET_UART_HANDLE_POINTER(id) (LPUART ## id ##_HND )
int foo()
{
return NUMBER_OF_UARTS
}
void *bar()
{
return GET_UART_HANDLE_POINTER(1)
}
void *zoo()
{
return GET_UART_HANDLE_POINTER(2)
}
And the preprocessed code:
int foo()
{
return (1 + 0)
}
void *bar()
{
return (((void *)0x4567800) )
}
void *zoo()
{
return (nullptr )
}
https://godbolt.org/z/c6shzqbcj

Why ifndef is not allowed inside a macro?

I am trying to write something like this:
#define set(x){cout<< x}
int main() {
set(#ifdef A 1 #else 3 #endif );
return 0;
}
But it does not work, my question is why?
Why doesn't C allow the code to work? what the problem with ifndef inside a macro?
Who said no?
set(
#ifdef A
1
#else
3
#endif
);
The above snippet works as expected. Demo on Godbolt
# is a special character that starts a preprocessor directive and must be at the start of the line (after optional whitespaces) so you must separate into new lines. Anyway that's not what people usually do, because they'll do like this
#ifdef A
set(1);
#else
set(3);
#endif
or
#ifdef A
#define VAL 1
#else
#define VAL 3
#endif
set(VAL);
Note that cout << is not C and you're missing a semicolon in the macro. It should be {cout<< x;}

Get a different value with macro every time it's used [duplicate]

I'm writing a bunch of related preprocessor macros, one of which generates labels which the other one jumps to. I use them in this fashion:
MAKE_FUNNY_JUMPING_LOOP(
MAKE_LABEL();
MAKE_LABEL();
)
I need some way to generate unique labels, one for each inner MAKE_LABEL call, with the preprocessor. I've tried using __LINE__, but since I call MAKE_LABEL inside another macro, they all have the same line and the labels collide.
What I'd like this to expand to is something like:
MAKE_FUNNY_JUMPING_LOOP(
my_cool_label_1: // from first inner macro
...
my_cool_label_2: // from second inner macro
...
)
Is there a way to generate hashes or auto-incrementing integers with the preprocessor?
If you're using GCC or MSVC, there is __COUNTER__.
Other than that, you could do something vomit-worthy, like:
#ifndef USED_1
#define USED_1
1
#else
#ifndef USED_2
#define USED_2
2
/* many many more */
#endif
#endif
I use this:
#define MERGE_(a,b) a##b
#define LABEL_(a) MERGE_(unique_name_, a)
#define UNIQUE_NAME LABEL_(__LINE__)
int main()
{
int UNIQUE_NAME = 1;
return 0;
}
... and get the following:
int main()
{
int unique_name_8 = 1;
return 0;
}
As others noted, __COUNTER__ is the easy but nonstandard way of doing this.
If you need extra portability, or for other cool preprocessor tricks, the Boost Preprocessor library (which works for C as well as C++) will work. For example, the following header file will output a unique label wherever it's included.
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/slot/slot.hpp>
#if !defined(UNIQUE_LABEL)
#define UNIQUE_LABEL
#define BOOST_PP_VALUE 1
#include BOOST_PP_ASSIGN_SLOT(1)
#undef BOOST_PP_VALUE
#else
#define BOOST_PP_VALUE BOOST_PP_INC(BOOST_PP_SLOT(1))
#include BOOST_PP_ASSIGN_SLOT(1)
#undef BOOST_PP_VALUE
#endif
BOOST_PP_CAT(my_cool_label_, BOOST_PP_SLOT(1)):
Sample:
int main(int argc, char *argv[]) {
#include "unique_label.h"
printf("%x\n", 1234);
#include "unique_label.h"
printf("%x\n", 1234);
#include "unique_label.h"
return 0;
}
preprocesses to
int main(int argc, char *argv[]) {
my_cool_label_1:
printf("%x\n", 1234);
my_cool_label_2:
printf("%x\n", 1234);
my_cool_label_3:
return 0;
}
I can't think of a way to automatically generate them but you could pass a parameter to MAKE_LABEL:
#define MAKE_LABEL(n) my_cool_label_##n:
Then...
MAKE_FUNNY_JUMPING_LOOP(
MAKE_LABEL(0);
MAKE_LABEL(1);
)
You could do this:
#define MAKE_LABEL() \
do { \
my_cool_label: \
/* some stuff */; \
goto my_cool_label; \
/* other stuff */; \
} while (0)
This keeps the scope of the label local, allowing any number of them inside the primary macro.
If you want the labels to be accessed more globally, it's not clear how your macro "MAKE_FUNNY_JUMPING_LOOP" references these labels. Can you explain?
It doesn't seem possible with a standard preprocessor, although you could fake it out by putting parameters within MAKE_LABEL or MAKE_FUNNY_JUMPING_LOOP, and use token pasting to create the label.
There's nothing preventing you from making your own preprocessing script that does the automatic increment for you. However, it won't be a standard C/C++ file in that case.
A list of commands available: http://www.cppreference.com/wiki/preprocessor/start

Is there a neat method to output text to debugging pane?

I would like to display some log messages when debugging. One option is to use the very ugly
#ifdef DEBUG
std::cout << "I'm in debug mode!\n";
#endif
In the JUCE library, there is a nice macro that outputs text to the debugging pane
DBG("I'm in debug mode!")
The juce solution also allows you to do neat stuff like the following that would be desirable
int x = 4;
DBG(String("x=") + String(x))
I would like to know if a similarly neat method exists in std:: or boost::
Why not just write your own:
#ifdef DEBUG
#define DBG(x) std::cout << x;
#else
#define DBG(x)
#endif
For namespaces
namespace DBG
{
inline void DBG(const char* x)
{
#ifdef DEBUG
std::cout << x;
#endif
}
}
If you want something like printf, you should use a bit another macros:
void DebugPrintLn(const char* format, ...);
inline void Nothing(...) {}
#ifdef DEBUG
#define DBG DebugPrintLn
#else
#define DBG Nothing // Or __noop on Visual C++
#endif
Using Nothing is portable, but arguments still computed (__noop guarantees that any of argument will be not computed, VC++ specific). Better if you can use macros variable arguments (both available on GCC and latest VC++): you may even skip any argument computation in portable way:
#ifdef DEBUG
#define DBG(...) DebugPrintLn(__VAR_ARGS__)
#else
#define DBG(...) ((void)0)
#endif
In any case, you use it the same way:
DBG("Lucky day: %s %i", "Friday", 13);
I have also written my own portable TRACE macro. I share it here:
#ifdef ENABLE_TRACE
# ifdef _MSC_VER
# include <windows.h>
# include <sstream>
# define TRACE(x) \
do { std::stringstream s; s << (x); \
OutputDebugString(s.str().c_str()); \
} while(0)
# else
# include <iostream>
# define TRACE(x) std::clog << (x)
# endif // or std::cerr << (x) << std::flush
#else
# define TRACE(x)
#endif
example:
#define ENABLE_TRACE //can depend on _DEBUG or NDEBUG macros
#include "my_above_trace_header.h"
int main (void)
{
int v1 = 123;
double v2 = 456.789;
TRACE ("main() v1="<< v1 <<" v2="<< v2 <<'\n');
}
Any improvements/suggestions/contributions are welcome ;-)

How do I implement no-op macro (or template) in C++?

How do I implement no-op macro in C++?
#include <iostream>
#ifdef NOOP
#define conditional_noop(x) what goes here?
#else
#define conditional_noop(x) std::cout << (x)
#endif
int main() {
conditional_noop(123);
}
I want this to do nothing when NOOP is defined and print "123", when NOOP is not defined.
While leaving it blank is the obvious option, I'd go with
#define conditional_noop(x) do {} while(0)
This trick is obviously no-op, but forces you to write a semicolon after conditional_noop(123).
As mentioned before - nothing.
Also, there is a misprint in your code.
it should be #else not #elif. if it is #elif it is to be followed by the new condition
#include <iostream>
#ifdef NOOP
#define conditional_noop(x) do {} while(0)
#else
#define conditional_noop(x) std::cout << (x)
#endif
Have fun coding!
EDIT: added the [do] construct for robustness as suggested in another answer.
Defining the macro to be void conveys your intent well.
#ifdef NOOP
#define conditional_noop(x) (void)0
#else
#ifdef NOOP
#define conditional_noop(x)
#elif
nothing!
#ifdef NOOP
static inline void conditional_noop(int x) { }
#else
static inline void conditional_noop(int x) { std::cout << x; }
#endif
Using inline function void enables type checking, even when NOOP isn't defined. So when NOOP isn't defined, you still won't be able to pass a struct to that function, or an undefined variable.
This will eventually prevent you from getting compiler errors when you turn the NOOP flag on.
You can just leave it blank. You don't need to follow the #define with anything.
Like others have said, leave it blank.
A trick you should use is to add (void)0 to the macro, forcing users to add a semicolon after it:
#ifdef NOOP
#define conditional_noop(x) (void)0
#else
#define conditional_noop(x) std::cout << (x); (void)0
#endif
In C++, (void)0 does nothing. This article explains other not-as-good options, as well as the rationale behind them.
As this is a macro, you should also consider a case like
if (other_cond)
conditional_noop(123);
to be on the safe side, you can give an empty statement like
#define conditional_noop(X) {}
for older C sometimes you need to define the empty statment this way (should also get optimized away):
#define conditional_noop(X) do {} while(0)
I think that a combination of the previous variants is a good solution:
#ifdef NOOP
static inline void conditional_noop(int x) do {} while(0)
#else
static inline void conditional_noop(int x) do { std::cout << x; } while(0)
#endif
The good thing is that these two codes differ only inside a block, which means that their behaviour for the outside is completely identical for the parser.