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:
static const int var = 5;
#define var 5
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 liketrue
,false
,null
,__FILE__
), whereasdefine()
takes any expression. Since PHP 5.6 constant expressions are allowed inconst
as well:const BIT_5 = 1 << 5; // Valid since PHP 5.6 and invalid previously
define('BIT_5', 1 << 5); // Always validconst
takes a plain constant name, whereasdefine()
accepts any expression as name. This allows to do things like this:for ($i = 0; $i < 32; ++$i) {
define('BIT_' . $i, 1 << $i);
}const
s are always case sensitive, whereasdefine()
allows you to define case insensitive constants by passingtrue
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, whiledefine()
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, whiledefine()
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 const
s 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.
const
s are much more compiler and debugger friendly than #define
s. 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 #define
s and const
s 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
const
s 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 enum
s 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.
- 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
- When we don't need to store constants in a variable.
#define MAX_BOUND 1000
#define MIN_BOUND 10
- 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
- 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
What Is "Strip" (Gcc Application) Used For
How to Compile for Windows Xp with Visual Studio 2012
How to Use C++11 Enum Class for Flags
C++ Overloaded Function as Template Argument
Base Pointer to Array of Derived Objects
Qt3D. Draw Transparent Qspheremesh Over Triangles
Ostream Chaining, Output Order
Can a Single Member of a Class Template Be Partially Specialized
General Use Cases for C++ Containers
Differencebetween an Empty and a Null Std::Shared_Ptr in C++
Constant Variables Not Working in Header
Why Can't Visual Studio Find My Dll