Differencebetween #Define and Const

What is the difference between #define and const?

The #define directive is a preprocessor directive; the preprocessor replaces those macros by their body before the compiler even sees it. Think of it as an automatic search and replace of your source code.

A const variable declaration declares an actual variable in the language, which you can use... well, like a real variable: take its address, pass it around, use it, cast/convert it, etc.

Oh, performance: Perhaps you're thinking that avoiding the declaration of a variable saves time and space, but with any sensible compiler optimisation levels there will be no difference, as constant values are already substituted and folded at compile time. But you gain the huge advantage of type checking and making your code known to the debugger, so there's really no reason not to use const variables.

static const vs #define vs enum

It depends on what you need the value for. You (and everyone else so far) omitted the third alternative:

  1. static const int var = 5;
  2. #define var 5
  3. enum { var = 5 };

Ignoring issues about the choice of name, then:

  • If you need to pass a pointer around, you must use (1).
  • Since (2) is apparently an option, you don't need to pass pointers around.
  • Both (1) and (3) have a symbol in the debugger's symbol table - that makes debugging easier. It is more likely that (2) will not have a symbol, leaving you wondering what it is.
  • (1) cannot be used as a dimension for arrays at global scope; both (2) and (3) can.
  • (1) cannot be used as a dimension for static arrays at function scope; both (2) and (3) can.
  • Under C99, all of these can be used for local arrays. Technically, using (1) would imply the use of a VLA (variable-length array), though the dimension referenced by 'var' would of course be fixed at size 5.
  • (1) cannot be used in places like switch statements; both (2) and (3) can.
  • (1) cannot be used to initialize static variables; both (2) and (3) can.
  • (2) can change code that you didn't want changed because it is used by the preprocessor; both (1) and (3) will not have unexpected side-effects like that.
  • You can detect whether (2) has been set in the preprocessor; neither (1) nor (3) allows that.

So, in most contexts, prefer the 'enum' over the alternatives. Otherwise, the first and last bullet points are likely to be the controlling factors — and you have to think harder if you need to satisfy both at once.

If you were asking about C++, then you'd use option (1) — the static const — every time.

PHP | define() vs. const

As of PHP 5.3 there are two ways to define constants: Either using the const keyword or using the define() function:

const FOO = 'BAR';
define('FOO', 'BAR');

The fundamental difference between those two ways is that const defines constants at compile time, whereas define defines them at run time. This causes most of const's disadvantages. Some disadvantages of const are:

  • const cannot be used to conditionally define constants. To define a global constant, it has to be used in the outermost scope:

     if (...) {
    const FOO = 'BAR'; // Invalid
    }
    // but
    if (...) {
    define('FOO', 'BAR'); // Valid
    }

    Why would you want to do that anyway? One common application is to check whether the constant is already defined:

     if (!defined('FOO')) {
    define('FOO', 'BAR');
    }
  • const accepts a static scalar (number, string or other constant like true, false, null, __FILE__), whereas define() takes any expression. Since PHP 5.6 constant expressions are allowed in const as well:

     const BIT_5 = 1 << 5;    // Valid since PHP 5.6 and invalid previously
    define('BIT_5', 1 << 5); // Always valid
  • const takes a plain constant name, whereas define() accepts any expression as name. This allows to do things like this:

     for ($i = 0; $i < 32; ++$i) {
    define('BIT_' . $i, 1 << $i);
    }
  • consts are always case sensitive, whereas define() allows you to define case insensitive constants by passing true as the third argument (Note: defining case-insensitive constants is deprecated as of PHP 7.3.0 and removed since PHP 8.0.0):

     define('FOO', 'BAR', true);
    echo FOO; // BAR
    echo foo; // BAR

So, that was the bad side of things. Now let's look at the reason why I personally always use const unless one of the above situations occurs:

  • const simply reads nicer. It's a language construct instead of a function and also is consistent with how you define constants in classes.

  • const, being a language construct, can be statically analysed by automated tooling.

  • const defines a constant in the current namespace, while define() has to be passed the full namespace name:

     namespace A\B\C;
    // To define the constant A\B\C\FOO:
    const FOO = 'BAR';
    define('A\B\C\FOO', 'BAR');
  • Since PHP 5.6 const constants can also be arrays, while define() does not support arrays yet. However, arrays will be supported for both cases in PHP 7.

     const FOO = [1, 2, 3];    // Valid in PHP 5.6
    define('FOO', [1, 2, 3]); // Invalid in PHP 5.6 and valid in PHP 7.0

Finally, note that const can also be used within a class or interface to define a class constant or interface constant. define cannot be used for this purpose:

class Foo {
const BAR = 2; // Valid
}
// But
class Baz {
define('QUX', 2); // Invalid
}

Summary

Unless you need any type of conditional or expressional definition, use consts instead of define()s - simply for the sake of readability!

static const vs #define

Personally, I loathe the preprocessor, so I'd always go with const.

The main advantage to a #define is that it requires no memory to store in your program, as it is really just replacing some text with a literal value. It also has the advantage that it has no type, so it can be used for any integer value without generating warnings.

Advantages of "const"s are that they can be scoped, and they can be used in situations where a pointer to an object needs to be passed.

I don't know exactly what you are getting at with the "static" part though. If you are declaring globally, I'd put it in an anonymous namespace instead of using static. For example

namespace {
unsigned const seconds_per_minute = 60;
};

int main (int argc; char *argv[]) {
...
}

#define vs const in Objective-C

First, I found that its not possible to define the type of the constant using #define, why is that?

Why is what? It's not true:

#define MY_INT_CONSTANT ((int) 12345)

Second, are there any advantages to use one of them over the another one?

Yes. #define defines a macro which is replaced even before compilation starts. const merely modifies a variable so that the compiler will flag an error if you try to change it. There are contexts in which you can use a #define but you can't use a const (although I'm struggling to find one using the latest clang). In theory, a const takes up space in the executable and requires a reference to memory, but in practice this is insignificant and may be optimised away by the compiler.

consts are much more compiler and debugger friendly than #defines. In most cases, this is the overriding point you should consider when making a decision on which one to use.

Just thought of a context in which you can use #define but not const. If you have a constant that you want to use in lots of .c files, with a #define you just stick it in a header. With a const you have to have a definition in a C file and

// in a C file
const int MY_INT_CONST = 12345;

// in a header
extern const int MY_INT_CONST;

in a header. MY_INT_CONST can't be used as the size of a static or global scope array in any C file except the one it is defined in.

However, for integer constants you can use an enum. In fact that is what Apple does almost invariably. This has all the advantages of both #defines and consts but only works for integer constants.

// In a header
enum
{
MY_INT_CONST = 12345,
};

Finally, which way is more efficient and/or more secure?

#define is more efficient in theory although, as I said, modern compilers probably ensure there is little difference. #define is more secure in that it is always a compiler error to try to assign to it

#define FOO 5

// ....

FOO = 6; // Always a syntax error

consts can be tricked into being assigned to although the compiler might issue warnings:

const int FOO = 5;

// ...

(int) FOO = 6; // Can make this compile

Depending on the platform, the assignment might still fail at run time if the constant is placed in a read only segment and it's officially undefined behaviour according to the C standard.

Personally, for integer constants, I always use enums for constants of other types, I use const unless I have a very good reason not to.

Difference between static const and #define in Objective-C

#define myInteger 5

is a preprocessor macro. The preprocessor will replace every occurrence of myInteger with 5 before the compiler is started. It's not a variable, it's just sort of an automatic find-and-replace mechanism.

static const NSInteger myInteger = 5;

This is a "real" variable that is constant (can't be changed after declaration). Static means that it will be a shared variable across multiple calls to that block.

Difference between `constexpr` and `#define`

Statements defined using #define are called macros. And macros are used in a multitude of uses.

  1. We can use them to conditionally compile sections of code.
#ifdef ONE
int AddOne(int x) { return x + 1; }

#else
int AddTwo(int x) { return x + 2; }

#endif

  1. When we don't need to store constants in a variable.
#define MAX_BOUND 1000
#define MIN_BOUND 10

  1. For places where we can use a macros to change the type of data.
#ifdef USE_WIDE_CHAR
#define TEXT(...) L##__VA_ARGS__

#else
#define TEXT(...) __VA_ARGS__

#endif

  1. To define keywords based on a condition.
#ifdef BUILD_DLL
#define DLL_API __declspec(dllexport)

#else
#define DLL_API __declspec(dllimport)

#endif

Since they are resolved before the actual compilation phase, we can make small improvement to the source code depending on certain factors (platforms, build systems, architecture, etc...).

constexpr essentially states that a variable or function can be resolved at compile time, but is not guaranteed.

I feel like constexpr is just a #define where the type can be chosen.

Its not completely true. As I stated before, because they are resolved before the compilation phase, we can take some advantages of it. The only common use would be for constant values which the compiler could easily replace as an optimization. Apart from that, the use cases are different.

In C++, is it better to use #define or const to avoid magic numbers?

Don't worry about efficiency in this case since all of them will be computed in compile-time.

You should stop using Macros (at least to define constants) whenever you can. Macros are wild things against namespaces and scopes. On the other hand const objects have type and this can reduce unintended mistakes.

It's always useful to read Stroustrup's piece of advises: "So, what's wrong with using macros?"

What is the difference between a macro and a const in C++?

Macros and constants are not remotely the same thing, each is sometimes appropriate for the circumstances, and your answer only scratches at the surface of the difference. Also, C++ has two different kinds of constants.

A constant defined with the const qualifier is best thought of as an unmodifiable variable. It has all the properties of a variable: it has a type, it has a size, it has linkage, you can take its address. (The compiler might optimize away some of these properties if it can get away with it: for instance, constants whose address is never used may not get emitted into the executable image. But this is only by the grace of the as-if rule.) The only thing you can't do to a const datum is change its value. A constant defined with enum is a little different. It has a type and a size, but it doesn't have linkage, you can't take its address, and its type is unique. Both of these are processed during translation phase 7, so they can't be anything but an lvalue or rvalue. (I'm sorry about the jargon in the preceding sentence, but I would have to write several paragraphs otherwise.)

A macro has far fewer constraints: it can expand to any sequence of tokens, as long as the overall program remains a well-formed program. It doesn't have any of the properties of a variable. Applying sizeof or & to a macro may or may not do something useful, depending on what the macro expands to. Macros are sometimes defined to expand to numeric literals, and such macros are sometimes thought of as constants, but they're not: "the compiler proper" (that is, translation phase 7) sees them as numeric literals.

It is generally considered good practice, nowadays, not to use a macro when a constant will do. Macros don't obey the same scoping rules as all other identifiers, which can be confusing, and if you use a constant you give more information to translation phase 7 and thus also to the debugger. However, macros permit you to do things that cannot be done any other way, and if you need to do one of those things, you should not hesitate to use them. (Macros that are pulling their weight, in this sense, generally do not just expand to numeric literals, though I am not going to say never.)

EDIT: Here's an example of a macro doing something interesting. It is in no way, shape or form a constant. There may well be a way to get the same effect without a macro (if you know one that doesn't involve stringstreams, I'd be curious to hear about it!) but I think it makes a good illustration of both the power and the danger of macros (for the latter, consider what it would do if it was used outside of one very specific context...)

static double elapsed()
{ ... }
#define ELAPSED '[' << std::fixed << std::setprecision(2) << elapsed() << "] "

// usage:
for (vector<string>::iterator f = files.begin(); f != files.end(); f++) {
cout << ELAPSED << "reading file: " << *f << '\n';
process_file(*f);
}

Static const vs #define for efficiency in C

Consider the following 2 test files

Test1.c: Uses static const foo.

// Test1.c uses static const..

#include <stdio.h>

static const foo = 6;

int main() {
printf("%d", foo);
return 0;
}

Test2.c: uses macro.

// Test2.c uses macro..

#include <stdio.h>

#define foo 6

int main() {
printf("%d", foo);
return 0;
}

and the corresponding assembly equivalences when using gcc -O0(default) are follows,

Assembly for Test1.c:

  0000000000000000 <main>:
0: 55 push rbp
1: 48 89 e5 mov rbp,rsp
4: 48 83 ec 20 sub rsp,0x20
8: e8 00 00 00 00 call d <main+0xd>
d: b8 06 00 00 00 mov eax,0x6
12: 89 c2 mov edx,eax
14: 48 8d 0d 04 00 00 00 lea rcx,[rip+0x4] # 1f <main+0x1f>
1b: e8 00 00 00 00 call 20 <main+0x20>
20: b8 00 00 00 00 mov eax,0x0
25: 48 83 c4 20 add rsp,0x20
29: 5d pop rbp
2a: c3 ret
2b: 90 nop

Assembly for Test2.c:

  0000000000000000 <main>:
0: 55 push rbp
1: 48 89 e5 mov rbp,rsp
4: 48 83 ec 20 sub rsp,0x20
8: e8 00 00 00 00 call d <main+0xd>
d: ba 06 00 00 00 mov edx,0x6
12: 48 8d 0d 00 00 00 00 lea rcx,[rip+0x0] # 19 <main+0x19>
19: e8 00 00 00 00 call 1e <main+0x1e>
1e: b8 00 00 00 00 mov eax,0x0
23: 48 83 c4 20 add rsp,0x20
27: 5d pop rbp
28: c3 ret
29: 90 nop

In both the cases, it is not using external memory. But the difference is that, #define replaces foo by the value, static const is an instruction so it increments the instruction pointer to the next instruction and it uses 1 additional register to store the value.

By this, we can say that macro is better than static constants but the difference is minimum.

EDIT: When using -O3 compilation option (i.e at optimization on) both the test1.c and test2.c evaluates the same.

0000000000000000 <main>:
0: 48 83 ec 28 sub rsp,0x28
4: e8 00 00 00 00 call 9 <main+0x9>
9: 48 8d 0d 00 00 00 00 lea rcx,[rip+0x0] # 10 <main+0x10>
10: ba 06 00 00 00 mov edx,0x6
15: e8 00 00 00 00 call 1a <main+0x1a>
1a: 31 c0 xor eax,eax
1c: 48 83 c4 28 add rsp,0x28
20: c3 ret
21: 90 nop

So, gcc treats both static const and #define as the same when it optimize.



Related Topics



Leave a reply



Submit