9
#define dItemName        L"CellPhone"
Al Kepp
  • 5,831
  • 2
  • 28
  • 48
Christopher Peterson
  • 983
  • 7
  • 22
  • 32
  • http://stackoverflow.com/questions/3474949/over-reliance-on-macros/3475032#3475032 – DumbCoder Jan 17 '11 at 17:17
  • You might want to check out Scott Meyers' "Effective C++" - I think 3rd Edition is most recent. He does a great job addressing this and many other similar C++ issues. – westsider Jan 17 '11 at 17:20
  • What will be the usage of this `dItemName`? Add examples. – i486 Oct 13 '17 at 13:43
  • Does this answer your question? [Why would someone use #define to define constants?](https://stackoverflow.com/questions/6274008/why-would-someone-use-define-to-define-constants) – Thomas Weller Aug 17 '22 at 18:49

6 Answers6

16

Define it as a constant variable. It is a good programming practice.

const wchar_t *dItemName = L"CellPhone";

In case you need to know the lenght of your string somewhere later, then define it as an array:

const wchar_t dItemName[] = L"CellPhone";

Also, why #define is bad: It transforms all places where you use word dItemName to L"CellPhone". Example:

struct {
  int dItemName;
} SomeStruct;

will become invalid:

struct {
  int L"CellPhone";
} SomeStruct;
Al Kepp
  • 5,831
  • 2
  • 28
  • 48
  • Well, the literal is already strongly typed, but ala. You are missing a *. – Hans Passant Jan 17 '11 at 17:14
  • Did you forget a `*` or `std::wstring`? – Nikolai Fetissov Jan 17 '11 at 17:14
  • 3
    uhm... just to be picky... Literals are really not pointers, but arrays, so the correct definition would be: `const wchar_t dItemName[] = L"CellPhone";`. There is almost no difference, but there is some. In particular, the compiler knows the size of the array, but not the number of elements pointed by a pointer. – David Rodríguez - dribeas Jan 17 '11 at 17:28
6

One major problem with #define is that it is outside of the language itself and therefore is not limited to a given scope. You will replace dItemName anywhere in the translation unit, in all namespaces, classes, functions, etc.

I'd replace it with const std::wstring dItemName = L"CellPhone";

Fred Larson
  • 60,987
  • 18
  • 112
  • 174
6

Amusingly I could not find a single question pointing all the disadvantages, even the subject has certainly been discussed before.

First of all, not that in C (not C++) this is the way to declare a constant. This also explains why so many C++ developers still use it: when they come from C background or have been taught by / learned from people with C background, they tend to reproduce this C-ish behavior.

In C++, however, we have superior facilities.

#define does not define a constant, it defines a macro

  1. A macro knows no scope
  2. A macro is not type safe

A macro knows no scope:

They are preprocessing facilities: the preprocessor is not aware of the rules of the underlying language (whether asm, C or C++) and will always expand the symbols it has in stock with no regard for scope.

For this reason, it is usually recommended to use a specific set of symbols to set macros apart. People generally use ALL_CAPS symbols, though you need to remember that:

  • they should not contain two consecutive underscores
  • they should not begin by an underscore

in order to be compliant with the C++ standard.

A macro is not type safe.

As I said, the preprocessor ignores the underlying language rules, therefore the following does not strike it as strange:

#define FOO "foo"

int main(int argc, char* argv[])
{
  if (FOO) { ... }

  return 0;
}

On the other hand, using a proper type would prevent this unintentional mistake:

std::string const Foo = "foo";

Conclusion ?

You can use a #define if you wish, it's just you doing the extra work instead of the compiler, but that's your call. Personally: I am lazy :)

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
  • I am an obj-c developer, lately I have started to convert constants into constant variables (See Al Kepp's answer), which were initially defined macros. If not for code execution and constant definition, is there any good use for #define?(especially, but not specifically for obj-c) – Yunus Nedim Mehel Jan 31 '14 at 13:09
  • @YunusNedimMehel: My main use case is logging macros. If you want access to `__FILE__`/`__LINE__` at the point where the logging is invoked, macros are necessary, because functions, even inlined, will use the `__FILE__`/`__LINE__` where they're defined, not from point-of-use. Similarly, for C (not as important in C++ w/RAII & exceptions), having a project-wide convention for the name of the cleanup section in a function, w/macros that check returns and `goto` the cleanup section isn't terrible (the alternative is arrow-patterns), and only macros can `goto` in the point-of-use scope. – ShadowRanger Feb 28 '18 at 06:08
2

Pointing to define doing what they where invented for as a failure is - well blaming a knife for cutting.

If you dont not properly Name your defines with UPPERCASE_NAMES you will have troubles, but you will have those troubles anyway in C if you can not self-discipline your working style.

You can not use const to generate dynamically rearranging systems, so its not suited for any embedded Application that is tailored pre-compile to usage.Const can only be assigned pre-evaluation constants, so not even other const Expressions.

Just because a Tool doese not bow to the OO-Paradigm its does not suddenly become useless. Const is not equal replacement regarding functionality.

Pica
  • 386
  • 3
  • 10
2

#define is a preprocessor instruction that defines a macro. In your case macro dItemName with value L"CellPhone".

Macros are bad mostly because they are processed before the actual code is. This means that they aren't subjected to scopes and to the rules of C++ syntax. If you've got a variable somewhere called dItemName, things won't probably work: you'll get hard-to-understand compilation errors due to that.

The solution is to declare dItemName as a variable (in this case a const variable).

peoro
  • 25,562
  • 20
  • 98
  • 150
1

Because preprocessor macros, which you've just made, pollute every name scope. They are available everywhere and do not follow standard naming scope rules. Thus, with a macro like that, code like int dItemName = 5; instead gets f'ed over by the preprocessor to instead be int L"CellPhone" = 5;. A constant, global variable would not do this.

All other issues aside, this is IMNSHO the worse issue with macro definitions.

Edward Strange
  • 40,307
  • 7
  • 73
  • 125