How does one prevent simple macro substitution?
e.g.
#define number 0x10
int number = 0x5;
I know this can be done for function-style macros, like min and max, by surrounding the macro with parentheses (thus, separating it from the adjacent parentheses that would've been used for the args):
#define max(...)
void (max)();
My current method is to push the macro value, undefine it, use it, then pop the original value.
You can't prevent macro substitution.
That's one of the reasons why macros are usually all caps:
#define NUMBER 0x10
int number = 0x5; // no problem here.
Even this can be done of course:
int number = NUMBER; // even this can be done of course
I would advise using const variables when you want to define constants instead of using macros. And to avoid name collisions maybe just add some prefix or suffix to the name or capitalize the name.
In c++ you can even use constexpr.
There is no standard way for this but you can do the following:
#define number 0x10
#pragma push_macro("number")
#undef number
int number = 0x5;
#pragma pop_macro("number")
The #undef directive undefines a constant or preprocessor macro defined previously using #define.
Refer: https://www.cprogramming.com/reference/preprocessor/undef.html
Related
Where should I prefer using macros and where should I prefer constexpr?
Aren't they basically the same?
#define MAX_HEIGHT 720
vs
constexpr unsigned int max_height = 720;
Aren't they basically the same?
No. Absolutely not. Not even close.
Apart from the fact your macro is an int and your constexpr unsigned is an unsigned, there are important differences and macros only have one advantage.
Scope
A macro is defined by the preprocessor and is simply substituted into the code every time it occurs. The preprocessor is dumb and doesn't understand C++ syntax or semantics. Macros ignore scopes such as namespaces, classes or function blocks, so you can't use a name for anything else in a source file. That's not true for a constant defined as a proper C++ variable:
#define MAX_HEIGHT 720
constexpr int max_height = 720;
class Window {
// ...
int max_height;
};
It's fine to have a member variable called max_height because it's a class member and so has a different scope, and is distinct from the one at namespace scope. If you tried to reuse the name MAX_HEIGHT for the member then the preprocessor would change it to this nonsense that wouldn't compile:
class Window {
// ...
int 720;
};
This is why you have to give macros UGLY_SHOUTY_NAMES to ensure they stand out and you can be careful about naming them to avoid clashes. If you don't use macros unnecessarily you don't have to worry about that (and don't have to read SHOUTY_NAMES).
If you just want a constant inside a function you can't do that with a macro, because the preprocessor doesn't know what a function is or what it means to be inside it. To limit a macro to only a certain part of a file you need to #undef it again:
int limit(int height) {
#define MAX_HEIGHT 720
return std::max(height, MAX_HEIGHT);
#undef MAX_HEIGHT
}
Compare to the far more sensible:
int limit(int height) {
constexpr int max_height = 720;
return std::max(height, max_height);
}
Why would you prefer the macro one?
A real memory location
A constexpr variable is a variable so it actually exists in the program and you can do normal C++ things like take its address and bind a reference to it.
This code has undefined behaviour:
#define MAX_HEIGHT 720
int limit(int height) {
const int& h = std::max(height, MAX_HEIGHT);
// ...
return h;
}
The problem is that MAX_HEIGHT isn't a variable, so for the call to std::max a temporary int must be created by the compiler. The reference that is returned by std::max might then refer to that temporary, which doesn't exist after the end of that statement, so return h accesses invalid memory.
That problem simply doesn't exist with a proper variable, because it has a fixed location in memory that doesn't go away:
int limit(int height) {
constexpr int max_height = 720;
const int& h = std::max(height, max_height);
// ...
return h;
}
(In practice you'd probably declare int h not const int& h but the problem can arise in more subtle contexts.)
Preprocessor conditions
The only time to prefer a macro is when you need its value to be understood by the preprocessor, for use in #if conditions, e.g.
#define MAX_HEIGHT 720
#if MAX_HEIGHT < 256
using height_type = unsigned char;
#else
using height_type = unsigned int;
#endif
You couldn't use a variable here, because the preprocessor doesn't understand how to refer to variables by name. It only understands basic very basic things like macro expansion and directives beginning with # (like #include and #define and #if).
If you want a constant that can be understood by the preprocessor then you should use the preprocessor to define it. If you want a constant for normal C++ code, use normal C++ code.
The example above is just to demonstrate a preprocessor condition, but even that code could avoid using the preprocessor:
using height_type = std::conditional_t<max_height < 256, unsigned char, unsigned int>;
Generally speaking, you should use constexpr whenever you may, and macros only if no other solution is possible.
Rationale:
Macros are a simple replacement in the code, and for this reason, they often generate conflicts (e.g. windows.h max macro vs std::max). Additionally, a macro which works may easily be used in a different way which can then trigger strange compilation errors. (e.g. Q_PROPERTY used on structure members)
Due to all those uncertainties, it is good code style to avoid macros, exactly like you'd usually avoid gotos.
constexpr is semantically defined, and thus typically generates far less issues.
Great answer by Jonathon Wakely. I'd also advise you to take a look at jogojapan's answer as to what the difference is between const and constexpr before you even go about considering the usage of macros.
Macros are dumb, but in a good way. Ostensibly nowadays they're a build-aid for when you want very specific parts of your code to only be compiled in the presence of certain build parameters getting "defined". Usually, all that means is taking your macro name, or better yet, let's call it a Trigger, and adding things like, /D:Trigger, -DTrigger, etc. to the build tools being used.
While there's many different uses for macros, these are the two I see most often that aren't bad/out-dated practices:
Hardware and Platform-specific code sections
Increased verbosity builds
So while you can in the OP's case accomplish the same goal of defining an int with constexpr or a MACRO, it's unlikely the two will have overlap when using modern conventions. Here's some common macro-usage that hasn't been phased out, yet.
#if defined VERBOSE || defined DEBUG || defined MSG_ALL
// Verbose message-handling code here
#endif
As another example for macro-usage, let's say you have some upcoming hardware to release, or maybe a specific generation of it that has some tricky workarounds that the others don't require. We'll define this macro as GEN_3_HW.
#if defined GEN_3_HW && defined _WIN64
// Windows-only special handling for 64-bit upcoming hardware
#elif defined GEN_3_HW && defined __APPLE__
// Special handling for macs on the new hardware
#elif !defined _WIN32 && !defined __linux__ && !defined __APPLE__ && !defined __ANDROID__ && !defined __unix__ && !defined __arm__
// Greetings, Outlander! ;)
#else
// Generic handling
#endif
Im trying to learn some c++, and I bumped into this code:
static const unsigned char t_CountBits13[8192] = {
#define B2(n) n, n+1, n+1, n+2
#define B4(n) B2(n), B2(n+1), B2(n+1), B2(n+2)
#define B6(n) B4(n), B4(n+1), B4(n+1), B4(n+2)
#define B8(n) B6(n), B6(n+1), B6(n+1), B6(n+2)
#define B10(n) B8(n), B8(n+1), B8(n+1), B8(n+2)
#define B12(n) B10(n), B10(n+1), B10(n+1), B10(n+2)
B12(0), B12(1)
};
I think this is pretty weird !
Question 1: Is this the same as:
#define B2(n) n, n+1, n+1, n+2
#define B4(n) B2(n), B2(n+1), B2(n+1), B2(n+2)
#define B6(n) B4(n), B4(n+1), B4(n+1), B4(n+2)
#define B8(n) B6(n), B6(n+1), B6(n+1), B6(n+2)
#define B10(n) B8(n), B8(n+1), B8(n+1), B8(n+2)
#define B12(n) B10(n), B10(n+1), B10(n+1), B10(n+2)
static const unsigned char t_CountBits13[8192] = {B12(0), B12(1)};
Question 2:
#define B2(n) n, n+1, n+1, n+2
Am I right to think that a C++ function can only return one value ? Because it seems like you define a function here that returns multiple (like lua for example)
Kind regards!
Answer 1: The array will be initialized with the same value. The preprocessed result will look a bit different with regards to white space, so textually it isn't the same, but the result of compilation should be identical.
Answer 2: As mentioned in the comments, these are not C++ functions, but are macros interpreted by the C pre-processor. These result in text expansion prior to the compiler interpreting it. The expansion in your example is too large to show here (2 * 4^6 = 8192 elements is a lot). I'll reduce it for an example.
Original source code:
static const unsigned char data[] = {
#define B2(n) n, n+1
#define B4(n) B2(n), B2(n+1)
B4(1), B4(2)
};
output of preprocessor (for example, as output by gcc -E tst.c:
# 1 "tst.c"
# 1 "<command-line"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line" 2
# 1 "tst.c"
static const unsigned char data[] = {
1, 1 +1, 1 +1, 1 +1 +1, 2, 2 +1, 2 +1, 2 +1 +1
};
Note the blank lines where the preprocessing directives were. Also note that the values are not the result of the arithmetic, but the text expansion. This is the code the compiler will actually interpret. Also note that the expansions are recursive through the #define macros defined above.
The lines starting with # are additional information from the preprocessor and includes things like defines from the command line and file information. It's fairly bland in the example, but if you were to have a #include <somefile.h> you'd see its contents, and the contents of the files it includes (recursively), as well as some # lines indicating the real line numbers of those locations (often used by the compiler for displaying warning and error messages, since by the time it gets it the line that used to be your line 5 might now be line 2592, but you'd expect the warning to indicate line 5).
Looking at the output of the preprocessor can be quite helpful debugging weird errors. When the message from the compiler just doesn't make sense, it can be an errant #define replacing text you didn't expect. For example, you might have the following code
int limit(int x) {
if (x > LIMIT) {
return LIMIT;
}
return x;
}
The compiler might say error: expected identifier or '(' before numeric constant on the line int limit(int x) {
If you look at the preprocessed output you might find
int 5(int x) {
and realize that the following line made it into your code (either original source file or from an included file)
#define limit 5
Note how limit is lower case, and we tried naming a function that, but the preprocessor replaced it with the 5. The #define should probably have been LIMIT (all uppercase)
This has been a bit of a long answer, but I hope illustrates the text-replacement nature of #defines and some hints at finding the intermediary representations of your own code.
Note: The actual output of your preprocessor depends on your toolchain. The information above holds for the GNU Compiler Collection. Some toolchains don't actually separate the pre-processor phase from the compilation phase, but simply behave as though they do, which is allowed by the language.
When I define this macro:
#define SQR(x) x*x
Let's say this expression:
SQR(a+b)
This expression will be replaced by the macro and looks like:
a+b*a+b
But, if I put a ++ operator before the expression:
++SQR(a+b)
What the expression looks like now? Is this ++ placed befor every part of SQR paramete? Like this:
++a+b*++a+b
Here I give a simple program:
#define SQR(x) x*x
int a, k = 3;
a = SQR(k+1) // 7
a = ++SQR(k+1) //9
When defining macros, you basically always want to put the macro parameters in parens to prevent the kind of weird behaviour in your first example, and put the result in parens so it can be safely used without side-effects. Using
#define SQR(x) ((x)*(x))
makes SQR(a+b) expand to ((a+b)*(a+b)) which would be mathematically correct (unlike a+b*a+b, which is equal to ab+a+b).
Putting things before or after a macro won't enter the macro. So ++SQR(x) becomes ++x*x in your example.
Note the following:
int a=3, b=1;
SQR(a+b) // ==> a+b*a+b = 3+1*3+1 = 7
++SQR(a+b) // ==> ++a+b*a+b ==> 4 + 1*4 + 1 = 9
// since preincrement will affect the value of a before it is read.
You're seeing the ++SQR(a+b) appear to increment by 2 since the preincrement kicks in before a i read either time, i.e. a increments, then is used twice and so the result is 2 higher than expected.
NOTE As #JonathanLeffler points out, the latter call invokes undefined behaviour; the evaluation is not guaranteed to happen left-to-right. It might produce different results on different compilers/OSes, and thus should never be relied on.
For C++ the right way to define this macro is to not use a macro, but instead use:
template<typename T> static T SQR( T a ) { return a*a; }
This will get right some horrible cases that the macro gets wrong:
For example:
SQR(++a);
with the function form ++a will be evaluated once. In the macro form you get undefined behaviour as you modify and read a value multiple times between sequence points (at least for C++)
A macro definition just replaces the code,hence it is generally preferable to put into parenthesis otherwise the code may replaced in a way you don't want.
Hence if you define it as :
#define SQR(x) ((x)*(x))
then
++SQR(a+b) = ++((a+b)*(a+b))
In your example, ++SQR(a+b) should be expanded as ++a+b*a+b.
So, if a == 3 and b == 1 you will get the answer 9 if the compiler evaluates it from left to right.
But your statement ++SQR(3+1) is not correct because it will be expanded as ++3+1*3+1 where ++3 is invalid.
In your preprocessor it evaluates to ++a+b*a+b. The right way is put brackets around each term and around the whole thing, like:
#define SQR(x) ((x)*(x))
At: http://www.learncpp.com/cpp-tutorial/110-a-first-look-at-the-preprocessor/
It mentions a directive called "Macro defines". What do we mean when we say "Macro"?
Thanks.
A macro is a preprocessor directive that defines a name that is to be replaced (or removed) by the preprocessor right before compilation.
Example:
#define MY_MACRO1 somevalue
#define MY_MACRO2
#define SUM(a, b) (a + b)
then if anywhere in the code (except in the string literals) there is a mention of MY_MACRO1 or MY_MACRO2 the preprocessor replaces this with whatever comes after the name in the #define line.
There can also be macros with parameters (like the SUM). In that case the preprocessor recognizes the arguments, example:
int x = 1, y = 2;
int z = SUM(x, y);
preprocessor replaces like this:
int x = 1, y = 2;
int z = (x + y);
only after this replacement the compiler gets to compile the resulting code.
A macro is a code fragment that gets substituted into your program by the preprocessor (before compilation proper begins). This may be a function-like block, or it may be a constant value.
A warning when using a function-like macro. Consider the following code:
#define foo(x) x*x
If you call foo(3), it will become (and be compiled as) 3*3 (=9). If, instead, you call foo(2+3), it will become 2+3*2+3, (=2+6+3=11), which is not what you want. Also, since the code is substituted in place, foo(bar++) becomes bar++ * bar++, incrementing bar twice.
Macros are powerful tools, but it can be easy to shoot yourself in the foot while trying to do something fancy with them.
"Macro defines" merely indicate how they are specified (with #define directives), while "Macro" is the function or expression that is defined.
There is little difference between them aside from semantics, however.
In a coding style question about infinite loops, some people mentioned they prefer the for(;;) style because the while(true) style gives warning messages on MSVC about a conditional expression being constant.
This surprised me greatly, since the use of constant values in conditional expressions is a useful way of avoiding #ifdef hell. For instance, you can have in your header:
#ifdef CONFIG_FOO
extern int foo_enabled;
#else
#define foo_enabled 0
#endif
And the code can simply use a conditional and trust the compiler to elide the dead code when CONFIG_FOO isn't defined:
if (foo_enabled) {
...
}
Instead of having to test for CONFIG_FOO every time foo_enabled is used:
#ifdef CONFIG_FOO
if (foo_enabled) {
...
}
#endif
This design pattern is used all the time in the Linux kernel (for instance, include/linux/cpumask.h defines several macros to 1 or 0 when SMP is disabled and to a function call when SMP is enabled).
What is the reason for that MSVC warning? Additionally, is there a better way to avoid #ifdef hell without having to disable that warning? Or is it an overly broad warning which should not be enabled in general?
A warning doesn't automatically mean that code is bad, just suspicious-looking.
Personally I start from a position of enabling all the warnings I can, then turn off any that prove more annoying than useful. That one that fires anytime you cast anything to a bool is usually the first to go.
I think the reason for the warning is that you might inadvertently have a more complex expression that evaluates to a constant without realizing it. Suppose you have a declaration like this in a header:
const int x = 0;
then later on, far from the declaration of x, you have a condition like:
if (x != 0) ...
You might not notice that it's a constant expression.
I believe it's to catch things like
if( x=0 )
when you meant
if( x==0 )
A simple way to avoid the warning would be:
#ifdef CONFIG_FOO
extern int foo_enabled;
#else
extern int foo_enabled = 0;
#endif