I'm new to Objective-C, and I have a few questions regarding const
and the preprocessing directive #define
.
First, I found that it's not possible to define the type of the constant using #define
. Why is that?
Second, are there any advantages to use one of them over the another one?
Finally, which way is more efficient and/or more secure?
In addition to other peoples comments, errors using
#define
are notoriously difficult to debug as the pre-processor gets hold of them before the compiler.From a C coder:
A
const
is simply a variable whose content cannot be changed.#define name value
, however, is a preprocessor command that replaces all instances of thename
withvalue
.For instance, if you
#define defTest 5
, all instances ofdefTest
in your code will be replaced with5
when you compile.It is important to understand the difference between the #define and the const instructions which are not meant to the same things.
const
const
is used to generate an object from the asked type that will be, once initialised, constant. It means that it is an object in the program memory and can be used as readonly. The object is generated every time the program is launched.#define
#define
is used in order to ease the code readability and future modifications. When using a define, you only mask a value behind a name. Hence when working with a rectangle you can define width and height with corresponding values. Then in the code, it will be easier to read since instead of numbers there will be names.If later you decide to change the value for the width you would only have to change it in the define instead of a boring and dangerous find/replace in your whole file. When compiling, the preprocessor will replace all the defined name by the values in the code. Hence, there is no time lost using them.
Since pre-processor directives are frowned upon, I suggest using a
const
. You can't specify a type with a pre-processor because a pre-processor directive is resolved before compilation. Well, you can, but something like:and use it as
which would be seen by the compiler as
You can, see my first snippet.
Generally having a
const
instead of a pre-processor directive helps with debugging, not as much in this case (but still does).Both are as efficient. I'd say the macro can potentially be more secure as it can't be changed during run-time, whereas a variable could.
I have used #define before to help create more methods out of one method like if I have something like.
But I also what to have a method that only takes 3 numbers and 2 numbers so instead of writing two new methods I am going to use the same one using the #define, like so.
I think this is a pretty cool thing to have, I know you can go straight to the method and just put nil in the spaces you don't want but if you are building a library it is very useful. Also this is how
are done.
Whereas I don't believe you can do this with constants. But constants do have there benefits over #define like you can't specify a type with a #define because it is a pre-processor directive that is resolved before compilation, and if you get an error with #define they are harder to debug then constants. Both have there benefits and downsides but I would say it all depends on the programmer to which one you decided to use. I have written a library with both them in using the #define to do what I have shown and constants for declaring constant variables which I need to specify a type on.
Why is what? It's not true:
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 aconst
(although I'm struggling to find one using the latest clang). In theory, aconst
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 notconst
. 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 aconst
you have to have a definition in a C file andin 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 andconst
s but only works for integer constants.#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 itconst
s can be tricked into being assigned to although the compiler might issue warnings: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 useconst
unless I have a very good reason not to.