[Home]  [Edit this page]  [Recent Changes]  [Special Pages]  [Help
CppDefine

(C++) #define

The preprocessor directive #define can be used for

Macros

Avoid macros's [1,2,7] when using C++ as there are better, type-safe alternatives.

The preprocessor directive #define is used to define macros. Prefer consts, enums and inlines to #defines[1,7].

A macro, in programming, is a identifier that gets replaced by the compiler or preprocessor to its value throughout the source code (this is a replace only for compiling purposes, and only used during compilation, so the source file is not changed in any way).

Example:
  1. include <stdio.h>
#define COUNT 5 int main() { for (int i = 0; i != COUNT; i++) { printf("Hello World!\n"); } }


This will print five times "Hello World!" followed by a newline. If you change the #define line to read
  1. define COUNT 10
then the "Hello World!" will be printed ten times.

That's because the preprocessor, when see the COUNT in the "for" line, replaces it by its value (which is defined in the "#define" line). It is common practice to write macro's like COUNT in capitals: 'If you must use macro's, use ugly names with lots of capital letters' [6].

The preprocessor considers that the value of the macro is any character after the space following its name, up to the next newline, so it is not recommended that you use a semicolon (";") to end a macro definition, else it will be considered part of the macro and will, possibly, generate a syntax error somewhere in your code where you use the macro.

Prefer consts over this type of #define[1,7,8].

Macro Functions

These are macros which can receive parameters.

Example:
  1. include <stdio.h>
#define INCREASE(x) x+1 int main() { int i = 0; printf("Increased: %i\n", INCREASE(i)); }


The above code would print "Increased: 1", since the initial value of the variable "i" is zero. The code the compiler will see, after preprocesing, is something like:
int main() 
{
    int i = 0;
    printf("Increased: %i\n", i+1);
}


Since the macro value is "x+1" and "x", in the example, is the variable "i".

Prefer inlines over this type of #define[1,7,9].

#include guards

The preprocessor statements #ifndef ,#define and #endif can be used for #include guards. These prevent a header file to be #included multiple times, causing a redeclaration error. Always write (internal) #include guards [3,10].

Example

  1. ifndef __MYHEADERFILE_H
  2. define __MYHEADERFILE_H
//Your header file
  1. endif


The assert statement

Also #define is used for the debugging #define NDEBUG (e.g. used by assert). Assert liberally to document internal assumptions and invariants [4,5,11]

  1. include <iostream>
  2. include <cassert>
double inverse(const double& value) { assert(value!=0.0); //Divisions by zero are illegal return 1.0/value; }


References

  • 1) Scott Meyers. Effective C++ (3rd edition).ISBN: 0-321-33487-6. Item 2: Prefer consts, enums and inlines to #defines
  • 2) Bjarne Stroustrup. The C++ Programming Language (3rd edition).ISBN: 0-201-88954-4. Chapter 7.9.4: 'Avoid macro's'
  • 3) Herb Sutter,Andrei Alexandrescu. C++ coding standards: 101 rules, guidelines, and best practices. ISBN: 0-32-111358-6. Chapter 24: 'Always write internal #include guards. Never write external #include guards'.
  • 4) Herb Sutter,Andrei Alexandrescu. C++ coding standards: 101 rules, guidelines, and best practices. ISBN: 0-32-111358-6. Chapter 68: 'Assert liberally to document internal assumptions and invariants'.
  • 5) Bjarne Stroustrup. The C++ Programming Language (3rd edition).ISBN: 0-201-88954-4. Advice 24.5.18: 'Explicitly express preconditions, postconditions, and other assertions as assertions'.
  • 6) Bjarne Stroustrup. The C++ Programming Language (3rd edition).ISBN: 0-201-88954-4. Chapter 7.9.10: 'If you must use macro's, use ugly names with lots of capital letters'.
  • 7) Jarrod Hollingworth, Bob Swart, Mark Cashman, Paul Gustavson. Sams C++ Builder 6 Developer's Guide. ISBN: 0-672-32480-6. Chapter 3, paragraph 'Know when to use the preprocessor', lines 1-2: 'It is not appropriate to use the preprocessor for defining constants or for creating function macro's. Instead, you should use const variables or enum types for constants and use inline function (or inline template function) to replace a function macro.
  • 8) Jesse Liberty. Sams teach yourself C++ in 24 hours. ISBN: 0-672-32224-2. Hour 21, chapter 'Using #define for constants': 'This is almost never a good idea, however, because #define merely makes a string substitution and does no type checking.'
  • 9) Jesse Liberty. Sams teach yourself C++ in 24 hours. ISBN: 0-672-32224-2. Hour 21, chapter 'Macros versus functions and templates': 'Macros suffer from four problems in C++. [...] The final problem, however is the biggest: macros are not type safe. [...] Templates overcome this problem.'
  • 10) Jesse Liberty. Sams teach yourself C++ in 24 hours. ISBN: 0-672-32224-2. Hour 21, chapter 'Inclusion and inclusion guards': 'It never hurts to use inclusion guards. Often they will save you hours of debugging time'. Also: hour 24, chapter 'include guards': 'All header files should use inclusion guards'.
  • 11) Jesse Liberty. Sams teach yourself C++ in 24 hours. ISBN: 0-672-32224-2. Hour 24, chapter 'assert()': 'Use assert freely'.


last edited (November 17, 2006) by bilderbikkel, Number of views: 7838, Current Rev: 23 (Diff)

[Edit this page]  [Page history]  [What links here]  [Discuss this topic]  [Printer Friendly]  

Members

Username:

Password:


Register
Forgot Password?




Programmers Heaven - for .NET, Java, C/C++ and WEB Developers!
© 1996-2008 Community Networks Ltd. All rights reserved. Reproduction in whole or in part, in any form or medium without express written permission is prohibited. Violators of this policy may be subject to legal action. Please read Terms Of Use and Privacy Statement for more information. Development by Tore Nestenius at .NET Consultant - Synchron Data.