Jump to content
  • Advertisement
Sign in to follow this  

Global variables in comparison to #define

This topic is 2139 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

As far as I can understand, if you use the pre processor command #define, for example, #define money 100, it'll replace all the instances of "money" and replace them with 100. As far as I know it is global and can be used all over your code?

What is the point of using #define instead of a global variable? Don't they pretty much do the same thing?
What's the difference between the two?

Share this post


Link to post
Share on other sites
Advertisement
I'm assuming you mean C++.

A define statement replaces -any- instance of "money" in your code, no matter if it's a variable or function in any namespace or scope. You get no namespace and the possibility of name clashes is pretty much guaranteed unless you give it a very long and unique name like "MYPROJECT_MONEY". A const global can be overridden in a scope defining another instance of "money" and you can even put it in a specific namespace avoiding other files declaring the same name.

Defines are uncontrollable and will find a way of leaking into places where you don't want it unless you give them very specific and ugly names. The windows.h header is a great example of this.. you better define LEAN_AND_MEAN before using it and hope all the defines really get undefined.

They're only "global" in the sense that if you include a file with it, you'll include the define it contains as well. But the same goes for globally defined const values, so there's no difference there.

Share this post


Link to post
Share on other sites

So basically you're all saying that if I can use a global constant rather than a #define, I should?

You can only benefit by doing so. Const values can be defined in headers as well. If you need a global variable (god forbid) you'll have to use the extern keyword in the header and define it in an implementation file.

Share this post


Link to post
Share on other sites
define is just a text replace, and does not care about the language. that can lead to some interesting abuses, and some interesting uses (the header include once thing). other than that, use language features, as they don't want to bite you in the back.

like #define max did all the time for me...

if you don't plan to ctrl-r replace-all-text, don't use #define.

Share this post


Link to post
Share on other sites
Preprocessor macros can be useful for many things, but I would not use them for constant values because you lose type safety and conflicts are possible that could create really hard to find bugs.

Share this post


Link to post
Share on other sites
The above advice is all perfectly valid and I don’t want my post to be misunderstood as a way to “get around” these faulty macro points—there is no real substitution for inlined functions etc.

I just want to add some safety tips for those few times when you really do need a macro.

  1. Naming macros such as “MONEY” is too generic. Due to the consequences of text replacement, you could end up with some very abstract and hard-to-trace errors if you use too-general names for your macros. The best way to combat this is to add a fake namespace to your macro. For example, in my engine there are 16 projects each with one namespace. lse, lss, lsm, lsg, etc. Within those projects, I replicate the namespaces within the macros. LSE_ELEMENTS( VAR ), LSG_OPENGL, LSG_DIRECTX11, etc.
  2. The above not only reduces conflicts but also lets know you 2 things: #1: Is this macro from my own library?, and #2: Which library? LSG_ = L. Spiro Graphics library. Easy.
  3. #undefine macros as soon as they are no longer needed. Header guards etc. should never be undefined, but within translation units (.cpp files) you might have some macros inside functions to make some tasks easier. An example in my engine is “#define LSG_HANDLE2CBUF( HANDLE )”, which, in DirectX 11 and DirectX 10, translates my custom handle into a custom cbuffer pointer, and is used only inside the CDirectX11CompiledShader and CDirectX10CompiledShader .CPP files. It is considered tidy to clean up after yourself, so #undef at the bottom of the .CPP files is a good idea. I have heard rumors of the possibility of macros “leaking” from one translation unit into another under some compilers so this is a good idea in general to avoid bugs.
  4. __ (2 underscores) is a prefix reserved for the system/compiler. If you want to make absolutely sure your macros will never conflict with anything, you could add some underscores in front, but make sure it is not just 2 underscores. At work we use 3.



L. Spiro Edited by L. Spiro

Share this post


Link to post
Share on other sites

__ (2 underscores) is a prefix reserved for the system/compiler. If you want to make absolutely sure your macros will never conflict with anything, you could add some underscores in front, but make sure it is not just 2 underscores. At work we use 3.


Anything starting with two underscores or one underscore and a capital letter is reserved for the compiler. So, anything starting with three underscores is reserved (since it also starts with two underscores) and any capitalized macro that starts with any underscores is reserved. Also, there can't be any sequence of two underscores in the identifier, even if it's not at the start. The compiler is not likely to define a macro that starts with three underscores but it is still allowed to do so.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!