This question already has answers here:
"static const" vs "#define" vs "enum"
(17 answers)
Closed 7 years ago.
I have seen a lot of programs using #define at the beginning. Why shouldn't I declare a constant global variable instead ?
(This is a C++ answer. In C, there is a major advantage to using macros, which is that they are pretty much the only way you can get a true constant-expression.)
What is the benefit of using #define to declare a constant?
There isn't one.
I have seen a lot of programs using #define at the beginning.
Yes, there is a lot of bad code out there. Some of it is legacy, and some of it is due to incompetence.
Why shouldn't I declare a constant global variable instead ?
You should.
A const object is not only immutable, but has a type and is far easier to debug, track and diagnose, since it actually exists at compilation time (and, crucially, has a name in a debug build).
Furthermore, if you abide by the one-definition rule, you don't have to worry about causing an almighty palaver when you change the definition of a macro and forget to re-compile literally your entire project, and any code that is a dependent of that project.
And, yes, it's ironic that const objects are still called "variables"; of course, in practice, they are not variable in the slightest.
What is the benefit of using #define to declare a constant?
Declaring a constant with #define is a superior alternative to using literals and magic numbers (that is, code is much better off with a value defined as #define NumDaysInWeek (7) than simply using 7), but not a superior alternative to defining proper constants.
You should declare a constant instead of #define-ing it, for the following reasons:
#define performs a token/textual replacement in the source code, not a semantic replacement.
This screws up namespace use (#defined variables are replaced with values and not containing a fully qualified name).
That is, given:
namespace x {
#define abc 1
}
x::abc is an error, because the compiler actually tries to compile x::1 (which is invalid).
abc on the other hand will always be seen as 1, forbidding you from redefining/reusing the identifier abc in any other local context or namespace.
#define inserts it's parameters textually, instead of as variables:
#define max(a, b) a > b ? a : b;
int a = 10, b = 5;
int c = max(a++, b); // (a++ > b ? a++ : b); // c = 12
#define has absolutely no semantic information:
#define pi 3.14 // this is either double or float, depending on context
/*static*/ const double pi = 3.14; // this is always double
#define makes you (the developer) see different code than the compiler
This may not be a big thing, but the errors created this way are obscure, unexpected and waste a lot of time (you could look at an error, where the code looks perfectly fine to you, and curse the compiler for half a day, only to discover later, that one of the symbols in your expression actually means something completely different).
If you get with a debugger to code using one of the declarations of pi above, the first one will cause the debugger to tell you that pi is an invalid symbol.
Edit (valid example for a local static const variable):
const result& some_class::some_function(const int key) const
{
if(map.count(key)) // map is a std::map<int,result> member of some_class
return map.at(key); // return a (const result&) to existing element
static const result empty_value{ /* ... */ }; // "static" is required here
return empty_value; // return a (const result&) to empty element
}
This shows a case when you have a const value, but it's storage needs to outlast the function, because you are returning a const reference (and the value doesn't exist in the data of some_class). It's a relatively rare case, but valid.
According to the "father" of C++, Stroustroup, defining constants using macros should be avoided.
The biggest Problems when using macros as constants include
Macros override all occurrences in the code. e.g. also variable definitions. This may result in compile Errors or undefined behavior.
Macros make the code very difficult to read and understand because the complexity of a macro can be hidden in a Header not clearly visible to the programmer
Related
For some kinds of programs I need to use a constant high value to indicate some properties of some variables. I mean let color[i] = 1000000; if the i node in a tree is unexplored. But I quite often miswrite the number of 0s at the end, so I just wondered whether is it better to do it this way:
#define UNEXPLORED 1000000;
color[i] = UNEXPLORED;
I remember that somewhere I have read that it's much better to avoid using #define. Is it right? How would you tackle this problem?
For simple constants, you can use either const or the new constexpr:
constexpr unsigned int UNEXPLORED = 1000000;
In a case like this, it's no difference between using const and constexpr. However, "variables" marked constexpr are evaluated at compile-time and not at run-time, and may be used in places that otherwise only accepts literals.
For example use constants.
const unsigned int UNEXPLORED = 1000000;
or enums
enum { UNEXPLORED = 1000000 };
In the use of constants the two answers above are correct, however #define is not limited to that use alone. Another example of the use of #define is macros.
Macros
Macros are preprocessor-utilised pieces of code, and they work exactly like other #define declarations in that regard. The preprocessor will literally swap out the occurrence of your defined symbol with the code of the macro. An example:
#define HELLO_MAC do{ std::cout << "Hello World" << std::endl; }while(false)
int main(int argc, char** argv)
{
HELLO_MAC;
}
That will literally swap out the HELLO_MAC symbol with the code I declared. If it were a constant it would do the exact same thing. So you can think of #defines for constants as a particular kind of macro.
With macros you can also pass parameters, and it is especially useful I find for enforcing logging/exception policies over code.
For example
#define THROW_EXCEPT( ex_type, ex_msg ) /
do{ throw ex_type( buildExString( (ex_msg), __LINE__, __FILE__ ) ); }while(false)
...
// somewhere else
THROW_EXCEPT( std::runtime_error, "Unsupported operation in current state" );
That code allows me to ensure that everyone logs with the line of the file that threw the exception.
Templates are often a better choice instead of macros, but I cannot use template functions for this example because I need to use the __LINE__ and __FILE__ functions from the place of the throw, not from the location of the template function.
Where should you not use macros? Anywhere you can use something else. Macros, like any #define are preprocessed, so the compiler does not see them at all. This means that there is never any symbols created for HELLO_MAC or THROW_EXCEPT, and so they cannot be seen in a debugger. They can also be confusing if you get compile errors, especially if they are long macros.
This question already has answers here:
What is double evaluation and why should it be avoided?
(4 answers)
Closed 3 years ago.
reading combase.cpp code, I find following:
/* We have to ensure that we DON'T use a max macro, since these will typically */
/* lead to one of the parameters being evaluated twice. Since we are worried */
/* about concurrency, we can't afford to access the m_cRef twice since we can't */
/* afford to run the risk that its value having changed between accesses. */
template<class T> inline static T ourmax( const T & a, const T & b )
{
return a > b ? a : b;
}
I don't understand why "max macro leads to one of the parameters being evaluated twice"?
Consider an usage like in this code sample:
#define max(a,b) (a>b?a:b)
int main()
{
int a = 0;
int b = 1;
int c = max(a++, b++);
cout << a << endl << b << endl;
return 0;
}
The intention probably was to print 1 and 2, but macro expands to:
int c = a++ > b++ ? a++ : b++;
b gets incremented twice, and the program prints 1 and 3.
Hence,
In some cases, expressions passed as arguments to macros can be evaluated more than once.
Although Als has quite clearly explained the immediate issue, I see two
larger issues. The first is simple: max can't be a macro, since it is
a standard function template, defined in <algorithm>. (In the case of
VC++, you need to define NOMINMAX in order to use <algorithm>. But
since it's always preferable to use a standard function when it does the
job, you should practically always add NOMINMAX to your preprocessor
defines, and be done with it.)
The second is even more worrisome, since it shows a lack of
understanding concerning the code. The comments make reference to
"concurrency", and suggest that by using the function, there are no
concurrency issues. This is simply incorrect. If any other thread (or
process, in the case of shared memory) may modify either of the
arguments, the behavior is undefined. In particular, as written, the
compiler likely would read one of the values twice; the arguments are
references. But regardless of how you write it, the compiler is allowed
to reread the values; and even if it doesn't, there's nothing to ensure
that the accesses are atomic. Whoever wrote the comment does not
understand the basic principles of multithreaded code.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
When are C++ macros beneficial?
Why is #define bad and what is the proper substitute?
Someone has told me that #define is bad. Well, I honestly don't not understand why its bad. If its bad, then what other way can I do this then?
#include <iostream>
#define stop() cin.ignore(numeric_limits<streamsize>::max(), '\n');
#define is not inherently bad. However, there are usually better ways of doing what you want. Consider an inline function:
inline void stop() {
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
(Really, you don't even need inline for a function like that. Just a plain ordinary function would work just fine.)
It's bad because it's indiscriminate. Anywhere you have stop() in your code will get replaced.
The way you solve it is by putting that code into its own method.
In C++, using #define is not forcibly bad, although alternatives should be preferred. There are some context, such as include guards in which there is no other portable/standard alternative.
It should be avoided because the C preprocessor operates (as the name suggests) before the compiler. It performs simple textual replacement, without regard to other definitions. This means the result input to the compiler sometimes doesn't make sense. Consider:
// in some header file.
#define FOO 5
// in some source file.
int main ()
{
// pre-compiles to: "int 5 = 2;"
// the compiler will vomit a weird compiler error.
int FOO = 2;
}
This example may seem trivial, but real examples exist. Some Windows SDK headers define:
#define min(a,b) ((a<b)?(a):(b))
And then code like:
#include <Windows.h>
#include <algorithm>
int main ()
{
// pre-compiles to: "int i = std::((1<2)?(1):(2));"
// the compiler will vomit a weird compiler error.
int i = std::min(1, 2);
}
When there are alternatives, use them. In the posted example, you can easily write:
void stop() {
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
For constants, use real C++ constants:
// instead of
#define FOO 5
// prefer
static const int FOO = 5;
This will guarantee that your compiler sees the same thing you do and benefit you with name overrides in nested scopes (a local FOO variable will override the meaning of global FOO) as expected.
It's not necessarily bad, it's just that most things people have used it for in the past can be done in a much better way.
For example, that snippet you provide (and other code macros) could be an inline function, something like (untested):
static inline void stop (void) {
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
In addition, there are all the other things that code macros force you to do "macro gymnastics" for, such as if you wanted to call the very badly written:
#define f(x) x * x * x + x
with:
int y = f (a + 1); // a + 1 * a + 1 * a + 1 + a + 1 (4a+2, not a^3+a)
int z = f (a++); // a++ * a++ * a++ + a++
The first of those will totally surprise you with its results due to the precedence of operators, and the second will give you undefined behaviour. Inline functions do not suffer these problems.
The other major thing that macros are used for is for providing enumerated values such as:
#define ERR_OK 0
#define ERR_ARG 1
: :
#define ERR_MEM 99
and these are better done with enumerations.
The main problem with macros is that the substitution is done early in the translation phase, and information is often lost because of this. For example, a debugger generally doesn't know about ERR_ARG since it would have been substituted long before the part of the translation process that creates debugging information.
But, having maligned them enough, they're still useful for defining simple variables which can be used for conditional compilation. That's pretty much all I use them for in C++ nowadays.
#define by itself is not bad, but it does have some bad properties to it. I'll list a few things that I know of:
"Functions" do not act as expected.
The following code seems reasonable:
#define getmax(a,b) (a > b ? a : b)
...but what happens if I call it as such?:
int a = 5;
int b = 2;
int c = getmax(++a,b); // c equals 7.
No, that is not a typo. c will be equal to 7. If you don't believe me, try it. That alone should be enough to scare you.
The preprocessor is inherently global
Whenever you use a #define to define a function (such as stop()), it acts across ALL included files after being discovered.
What this means is that you can actually change libraries that you did not write. As long as they use the function stop() in the header file, you could change the behavior of code you didn't write and didn't modify.
Debugging is more difficult.
The preprocessor does symbolic replacement before the code ever makes it to the compiler. Thus if you have the following code:
#define NUM_CUSTOMERS 10
#define PRICE_PER_CUSTOMER 1.10
...
double something = NUM_CUSTOMERS * PRICE_PER_CUSTOMER;
if there is an error on that line, then you will NOT see the convenient variable names in the error message, but rather will see something like this:
double something = 10 * 1.10;
So that makes it more difficult to find things in code. In this example, it doesn't seem that bad, but if you really get into the habit of doing it, then you can run into some real headaches.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C++ - enum vs. const vs. #define
Before I used #define I used to create constants in my main function and pass them where they were needed. I found that I passed them very often and it was kind of odd, especially array sizes.
More recently I have been using #define for the reason that I don't have to pass constants in my main to each individual function.
But now that I think of it, I could use global constants as well, but for some reason I have been a little hesitant towards them.
Which is the better practice: global constants or #define?
A side question, also related: Is passing constants from my main as I described a bad practice?
They don't do quite the same thing. #define lets you affect the code at compilation time, while global constants only come into effect at runtime.
Seeing as #define can only give you extra trouble because there's no checking going on with how you use it, you should use global constants when you can and #define when you must. It will be safer and more readable that way.
As for passing constants from main, it's not unreasonable because it makes the called functions more flexible to accept an argument from the caller than to blindly pull it out of some global. Of course it the argument isn't really expected to change for the lifetime of the program you don't have much to gain from that.
Using constants instead of #define is very much to be preferred. #define replaces the token dumbly in every place it appears, and can cause all sorts of unintended consequences.
Passing values instead of using globals is good practice. It makes the code more flexible and modular, and more testable. Try googling for "parameterise from above".
You should never use either #defines or const variables to represent array sizes; it's better to make them explicit.
Instead of:
#define TYPICAL_ARRAY_SIZE 4711
int fill_with_zeroes(char *array)
{
memset(array, 0, TYPICAL_ARRAY_SIZE);
}
int main(void)
{
char *za;
if((za = malloc(TYPICAL_ARRAY_SIZE)) != NULL)
{
fill_with_zeroes(za);
}
}
which uses a (shared, imagine it's in a common header or something) #define to communicate the array size, it's much better to just pass it to the function as a real argument:
void fill_with_zeroes(char *array, size_t num_elements)
{
memset(array, 0, num_elements); /* sizeof (char) == 1. */
}
Then just change the call site:
int main(void)
{
const size_t array_size = 4711;
char *za;
if((za = malloc(array_size)) != NULL)
{
fill_with_zeroes(za, array_size);
}
}
This makes the size local to the place that allocated it, there's no need for the called function to magically "know" something about its arguments that is not communicated through its arguments.
If the array is non-dynamically allocated, we can do even better and remove the repeated symbolic size even locally:
int main(void)
{
char array[42];
fill_with_zeroes(array, sizeof array / sizeof *array);
}
Here, the well-known sizeof x / sizeof *x expression is used to (at compile-time) compute the number of elements in the array.
Constants are better. The only difference between the two is that constants are type-safe.
You shouldn't use values defined with #define like const parameters. Defines are used mostly to prevent the compiler to compile some parts of code depending on your needings at compile time (platform dependent choices, optimization at compile time, ).
So if you are not using define for these reasons avoid that and use costant values.
I'm writing porting file-io set of functions from c into a c++ class. "Magic numbers" (unnamed constants) abound.
The functions read a file header which has a number of specific entries whose locations are currently denoted by magic numbers.
I was taught by a veteran programmer a couple years back that using "magic numbers" is inherently evil, and thus, I have since tried to avoid using unnamed constants in my port. So I want to create some sort of list of constants of where the entries are stored.
So far I've come up with two solutions that seem relatively safe -- use a namespace enclosed set of constants or a namespace enclosed enum.
Can I use either solution safely? Would there be any advantages to one over the other?
e.g.
OPTION 1
namespace hdr_pos {
const unsigned int item_1_pos=4;
const unsigned int item_2_pos=8;
const unsigned int item_3_pos=12;
const unsigned int item_4_pos=24;
const unsigned int item_5_pos=32;
};
OPTION 2
namespace hdr_pos {
enum e {
item_1_pos=4,
item_2_pos=8,
item_3_pos=12,
item_4_pos=24,
item_5_pos=32
};
};
Is there anyway to prevent duplicates, to catch if I change the positions due to a future update to the file header, but forget to change one of them?
Please keep this factual and non-subjective. If there is no advantage you know of, feel free to answer that.
Note: I would use more descriptive names, of course, in my actual implementation; I just called things item_<#>_... for examples sake...
I can see two advantages to using an enum. First, some debuggers can translate constants back into enum variable names (which can make debugging easier in some cases). Also, you can declare a variable of an enumerated type which can only hold a value from that enumeration. This can give you an additional form of type checking that you wouldn't have simply by using constants.
Checking to see if a value is duplicated might depend on your particular compiler. The easiest way to do so would probably be to write an external script that will parse your enum definition and report whether or not a value is duplicated (you can run this as part of your build process if you like).
I've dealt with this situation before, for error codes.
I have seen people using enums for error codes, and this pose some issues:
you can assign an int to the enum that doesn't not correspond to any value (too bad)
the value itself is declared in a header, meaning that error code reassignment (this happens...) breaks code compatibility, you also have to take care when adding elements...
you have to define all codes in the same header, even if often times some code are naturally restricted to a small portion of the application, because enums cannot be "extended"
there is no check that a same code is not assigned twice
you cannot iterate over the various fields of an enum
When designing my error codes solution, I thus chose another road: constants in a namespace, defined in source files, which address points 2 and 3. To gain in type safety though, the constants are not int, but a specific Code class:
namespace error { class Code; }
Then I can define several error files:
// error/common.hpp
namespace error
{
extern Code const Unknown;
extern Code const LostDatabaseConnection;
extern Code const LostNASConnection;
}
// error/service1.hpp
// error/service2.hpp
I didn't solved the arbitrary cast issue though (constructor is explicit, but public), because in my case I was required to forward error codes returned by other servers, and I certainly didn't want to have to know them all (that would have been too brittle)
However I did thought about it, by making the required constructor private and enforcing the use of a builder, we're even going to get 4. and 5. in a swoop:
// error/code.hpp
namespace error
{
class Code;
template <size_t constant> Code const& Make(); // not defined here
class Code: boost::totally_ordered<Code>
{
public:
Code(): m(0) {} // Default Construction is useful, 0 is therefore invalid
bool operator<(Code const& rhs) const { return m < rhs.m; }
bool operator==(Code const& rhs) const { return m == rhs.m; }
private:
template <size_t> friend Code const& Make();
explicit Code(size_t c): m(c) { assert(c && "Code - 0 means invalid"); }
size_t m;
};
std::set<Code> const& Codes();
}
// error/privateheader.hpp (inaccessible to clients)
namespace error
{
std::set<Code>& PrivateCodes() { static std::set<Code> Set; return Set; }
std::set<Code> const& Codes() { return PrivateCodes(); }
template <size_t constant>
Code const& Make()
{
static std::pair< std::set<Code>::iterator, bool > r
= PrivateCodes().insert(Code(constant));
assert(r.second && "Make - same code redeclared");
return *(r.first);
}
}
//
// We use a macro trick to create a function whose name depends
// on the code therefore, if the same value is assigned twice, the
// linker should complain about two functions having the same name
// at the condition that both are located into the same namespace
//
#define MAKE_NEW_ERROR_CODE(name, value) \
Make<value>(); void _make_new_code_##value ();
// error/common.cpp
#include "error/common.hpp"
#include "privateheader.hpp"
namespace error
{
Code const Unkown = MAKE_NEW_ERROR_CODE(1)
/// ....
}
A tad more work (for the framework), and only link-time/run-time check of the same assignment check. Though it's easy to diagnose duplicates simply by scanning for the pattern MAKE_NEW_ERROR_CODE
Have fun!
The title of your question suggests that the main reason you have doubts about using a enum is that your constants are non-iterative. But in C++ enum types are non-iterative already. You have to jump through quite a few hoops to make an iterative enum type.
I'd say that if your constants are related by nature, then enum is a pretty good idea, regardless of whether the constants are iterative or not. The main disadvantage of enums though is total lack of type control. In many cases you might prefer to have strict control over the types of your constant values (like have them unsigned) and that's something enum can't help you with (at least yet).
One thing to keep in mind is that you can't take the address of an enum:
const unsigned* my_arbitrary_item = &item_1_pos;
If they're purely constants and require no run-time stuff (like can't init enum with non-enum value) then they should just be const unsigned ints. Of course, the enum is less typing, but that's besides the point.