Take the 2-minute tour ×

Can someone point out the advantages and disadvantages of using #define versus constants? Most of my work is done in C and Objective-C.

share|improve this question
#define's don't respect scope. –  GManNickG Dec 22 '09 at 3:43

10 Answers 10

up vote 16 down vote accepted

Constants allow you to specify a datatype, which is (usually) an advantage. Macros are much more flexible, and therefore can get you into much more trouble if you're not careful.

Best practice is to use constants as much as possible, and use #define only when you really need a macro, not just a named literal value.

share|improve this answer
-1 for not mentioning that const in C is not a true (compile-time) constant, and therefore cannot be used in case labels, as array sizes, and in other contexts where a constant expression is required. There is a reason why #define is used so heavily in C (and const is used much more often in C++), and glossing over it makes for a bad answer to this question. –  Pavel Minaev Dec 22 '09 at 4:48
I did forget that const is weaker in C as you mention, but I think the best practice is still to use consts whenever possible. –  Asher Dunn Dec 22 '09 at 5:21
IMO, the best option is to actually use an anonymous enum for those integral constant expressions - it's kinda typed, it's scoped, no nameclashes etc, but it's also an integral constant. For everything else (for which being compile-time doesn't really matter - floats, strings etc), const is fine. Also note that anonymous enums are in ANSI C89, even though many people believe the contrary (since anonymous structs aren't there). –  Pavel Minaev Dec 22 '09 at 7:28
Another small drawback of enum is that any number suffix like U or LL will be dropped by the compiler, as an enum is always an int in standard C (though some compilers propose to use smaller types for embedded sw). –  calandoa Nov 6 '12 at 12:09

As 0A0D mentioned, there are #defines, enums, and const variables. It's worth noting that const-qualified variables are not considered to be compile-time constants in C and therefore can't be used in some circumstances (e.g. when declaring the size of an array).

enum constants are compile-time constants, however. For integral values, IMO it's usually better to prefer enums over const variables over #define.

share|improve this answer
I'm shocked that the sole answer that correctly pointed out the clear disadvantage of using const in C (and, by extension, Objective-C; note that this question isn't about C++!) isn't upmodded to the top. +1, and wish I could give this more. –  Pavel Minaev Dec 22 '09 at 4:46
So, to sum it up, the short rule is: for integral constants, use anonymous enums. For everything else, use const. Don't use #define except for proper macros, or conditionally included tokens. –  Pavel Minaev Dec 22 '09 at 7:30
What are anonymous enums? –  Michael Jan 14 '12 at 10:00
@Michael: enum types without a typename. For example, enum { foo = 42 }; is anonymous; enum bar { foo = 42 }; isn't. –  jamesdlin Jan 15 '12 at 6:52

Actually there are three ways of defining such constants,

  • #defines
  • enums
  • const variables

In C, everything is an int unless otherwise specified. I prefer enums when I have a number of related integer constants. Enums are clearly preferable when you don't care what the values are. But even when you do need to specify the values for all the constants, I like the mental grouping of an enum. Code documents itself better when you have the type, e.g.

Error MyFunc();

clearly returns one of a particular set of error codes, whereas

int MyFunc()

might return one of the #define'd list for Unix errno, or maybe something else, or maybe those plus some idiosyncratic values -- who knows? If you have more than one set of return codes, which set does this function use?

The more specific enum type name helps the tags facility in your editor, greps, debugging, and so on.

A strict lint may give you some warnings about using enums as integers, for example if you add or or them, or pass an enum to an int.

A const object is different from either an enum or a #define, particularly in C. In ANSI C, a const int takes up space just as a regular int; most compilers will also generate pointer references to this address rather than inlining the value. As a result, I rarely use const int's in C. (C++ has slightly different semantics, and so the choices are different there.)

Every compiler I've ever used has the option to store enums in the smallest space possible. Usually it's even the default option. To force wider enums when using such an option, I usually throw in an extra unsigned value:

typedef enum

    MyEnumForce16 = 7fff
} MyEnum;




enum Error_Code


#define OUT_OF_MEMORY 0
#define LOGIC_ERROR 2
#define FILE_NOT_FOUND 3




The #define statement is a pre-compiler directive. Technically, any line that begins with a # is something for the pre-compiler to act on. The pre-compiler will replace all instances of the defined token with its definition. So doing this:

#define DELAY 40
for (i=0;i<DELAY;i++) {
    for (j=0;j<DELAY;j++) {
        asm NOP;

is exactly the same as this (as far as the compiler is concerned):

    for (j=0;j<40;j++) {
        asm NOP;

When the compiler generates machine code, it will see the number 40 and use the immediate addressing mode in order to compare with the accumulator. The number 40 will be stored in the code as many times as you are referencing it. In this case it is twice. Here is the assembly generated by CodeWarrior Ver5:

7:    char i,j;
    8:    for (i=0;i<DELAY;i++) {
  0002 95       [2]             TSX   
  0003 7f       [2]             CLR   ,X
  0004          [5]     L4:     
    9:      for (j=0;j<DELAY;j++) {
  0004 6f01     [3]             CLR   1,X
  0006          [5]     L6:     
   10:        asm NOP;
  0006 9d       [1]             NOP   
  0007 6c01     [4]             INC   1,X
  0009 e601     [3]             LDA   1,X
  000b a128     [2]             CMP   #40  ;<---- notice opcode a1 and immediate constant 40, which is $28 in hexadecimal
  000d 25f7     [3]             BCS   L6
  000f 7c       [3]             INC   ,X
  0010 f6       [2]             LDA   ,X
  0011 a128     [2]             CMP   #40  ;<---- and here it is again.
  0013 25ef     [3]             BCS   L4
   11:      }
   12:    }
   13:  }
share|improve this answer
+1 for listing all available options, but it's worth expanding on the benefit of using enum, and disadvantage of const compared to enum and #define. –  Pavel Minaev Dec 22 '09 at 4:49

Constants have the advantage of being typed, so using them incorrectly can be discovered at compile time. It may not matter to you but constants take up space in memory while #defines do not (since they are replaced before actual compilation happens).

share|improve this answer
Constants need not take up space in memory, if you do not take their address (or otherwise treat them as lvalues). Any sane linker will optimize any such away. –  Pavel Minaev Dec 22 '09 at 4:48

Constants follow type safety measures, #defines are substituted outright. Also as GMan said, #define's don't respect scope.

share|improve this answer

Explanation for #define:A #define is either an immediate value or a macro.

Explanation for constant:A constant is a value of any type which can never change.

You can delcare a pointer to a const, but not to a #define, although a #define could be a pointer for eg: #define ADDRESS ((int *)0x0012)

So why we should use constant is as follows:

  • they obey the language's scoping rules
  • you can see them in the debugger
  • you can take their address if you need to
  • they don't create new "keywords" in your program.


Within a module, a C compiler could optimize a const as if it were a #define, if there are no pointers declared to the constant. In CPU terms, the const would become an "immediate" value. Other alternatives is that a const variable could be placed in the code area as opposed to the data area since it doesn't change. On some machines, declaring a ponter to a constant could cause an exception if you tried to modify the constant via the pointer.

There are cases where #define is needed, but you should generally avoid it when you have the choice. You should evaluate whether to use const or #define based on business value: time, money, risk.

share|improve this answer

Const is an object you can take its address, for example. Also it is type-safe, i.e. compiler knows what the constant's type is. Above does not apply to #define.

share|improve this answer
  1. const produces an lvalue, meaning its address can be taken. #define doesn't.
  2. #define can cause unintentional macro expansions, which can be a PITA to debug.
  3. As mentioned by others, #define doesn't have a type associated with it.

In general, I'd avoid the preprocessor like the plague for anything I didn't have to use it for, mostly because of the possibility of unintentional expansion and because the ALL_CAPS convention for mitigating this is unbelievably ugly.

share|improve this answer

1) #define's can be considered as tunable parameters that are independent of the datatypes, whereas constant's allow us to mention the datatype.

2) #define's replaces any code that follows that in the main program where ever they are referred to. In addition to this we can even have macro function performing a specific task, that could be called by passing the parameters alone. These are obviously not possible in the case of constant's.

So, they are used based on the relevance.

share|improve this answer

the benefit of using define is once you define the variable for exp: #define NUMBER 30, all the code in main will use that code with value 30. If you change the 30 to 40 it will directly change all value in main which using this variable (NUMBER).

share|improve this answer

Your Answer


