# \#define vs. const

**URL:** <https://forum.arduino.cc/t/define-vs-const/581308>\
**Category:** Programming\
**Created:** [March 22, 2019, 1:25pm UTC](https://forum.arduino.cc/t/define-vs-const/581308 "2019-03-22T13:25:06Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ken\_F](https://avatars.discourse-cdn.com/v4/letter/k/848f3c/32.png) [@Ken\_F](https://forum.arduino.cc/u/Ken_F)\
**Post date:** [March 22, 2019, 1:25pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/1 "2019-03-22T13:25:06Z")

</div>

Hi all,  
Could someone tell me what difference(s) there are when using #define vs. const to setup a reoccurring pin definition? I want to identify pin 2 with the name "Blank". Is one better than the other? (faster, uses less memory. etc)

ie.:  
#define Blank 2  
vs.  
const Blank 2

---

<div class="post-metadata">

**Author:** ![UKHeliBob](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ukhelibob/32/215663_2.png) [@UKHeliBob](https://forum.arduino.cc/u/UKHeliBob)\
**Post date:** [March 22, 2019, 1:46pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/2 "2019-03-22T13:46:45Z")

</div>

The first thing to note is that

```cpp
const Blank 2

```

is not valid code, which I assume you realise

---

<div class="post-metadata">

**Author:** ![MorganS](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/morgans/32/218718_2.png) [@MorganS](https://forum.arduino.cc/u/MorganS)\
**Post date:** [March 22, 2019, 1:47pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/3 "2019-03-22T13:47:47Z")

</div>

#define is like replacing the text. It gives the exact same result as a search-replace. So you can get unexpected results....

```cpp
#define THREE 1 + 2

  Serial.println( 2*THREE ); 
  Serial.println( 2*1 + 2 );

```

Can you see why both println statements will print "4" and not "6"?

You can use this to your advantage. The Arduino #define ISR does some clever text manipulation so that you use it like a function even though it is not a function.

The advantage of the const declaration is the compiler can check the type of the variable. (Which you forgot.)

In your simple example, the compiler will optimize the result down to the same machine code. Even if you didn't use the const keyword, it works out that it is a constant. The const declaration is more for your benefit, so you don't accidentally change it.

---

<div class="post-metadata">

**Author:** ![GypsumFantastic](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/gypsumfantastic/32/236274_2.png) [@GypsumFantastic](https://forum.arduino.cc/u/GypsumFantastic)\
**Post date:** [March 22, 2019, 2:11pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/4 "2019-03-22T14:11:31Z")

</div>

I always prefer const because it's C and I know how to do C (mostly).

#define uses the preprocessor which has its own set of rules and syntax, and I've never really spent much time learning preprocessor. Also it seems like it can sometimes throw you a curve-ball (as in MorganS's example above) if you don't pay attention. I know preprocessor is essential for other things, but for defining constants why even go there?

---

<div class="post-metadata">

**Author:** ![boolrules](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/boolrules/32/219130_2.png) [@boolrules](https://forum.arduino.cc/u/boolrules)\
**Post date:** [March 22, 2019, 2:43pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/5 "2019-03-22T14:43:26Z")

</div>

This hardly demonstrates a problem with the preprocessor.

> MorganS:  
> #define is like replacing the text. It gives the exact same result as a search-replace. So you can get unexpected results....
> 
> ```arduino
> #define THREE 1 + 2
> 
> ```

Serial.println( 2_THREE );  
&nbsp; Serial.println( 2_1 + 2 );

> ```arduino
> 
> Can you see why both println statements will print "4" and not "6"?
> 
> ```

If you understand why the 2nd println fails, you know why the 1st also failed. You shouldn't expect otherwise.

```arduino
#define THREE (1 + 2)    // the way you should write such an expression anywhere (if that IS what you mean)
#define THREE    3      // the obvious way

```

---

<div class="post-metadata">

**Author:** ![Danois90](https://avatars.discourse-cdn.com/v4/letter/d/50afbb/32.png) [@Danois90](https://forum.arduino.cc/u/Danois90)\
**Post date:** [March 22, 2019, 2:54pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/6 "2019-03-22T14:54:15Z")

</div>

Defines can be "dangerous" if carelessly used, unless you are absolutely sure what you are doing, you should use const instead. Defines can be "overwritten" causing a define to change its value, const declarations will not allow this and therefore they are safer to use.

And for the memory usage: Same, same - either it fits or it doesn't! 😉

---

<div class="post-metadata">

**Author:** ![MorganS](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/morgans/32/218718_2.png) [@MorganS](https://forum.arduino.cc/u/MorganS)\
**Post date:** [March 22, 2019, 3:16pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/7 "2019-03-22T15:16:46Z")

</div>

For trivial examples, pin numbers and whatever, the const is usually better. But #define is better used for calculation, where it looks more like a function.

In those cases, it is usually better to use an actual function, maybe with the `inline` compiler hint to encourage it to make the program faster by making it bigger.

Like any good tool, it can be used for many purposes, including hammering your own thumb.

---

<div class="post-metadata">

**Author:** ![Ken\_F](https://avatars.discourse-cdn.com/v4/letter/k/848f3c/32.png) [@Ken\_F](https://forum.arduino.cc/u/Ken_F)\
**Post date:** [March 22, 2019, 4:25pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/8 "2019-03-22T16:25:55Z")

</div>

Sorry UKHeliBob, I should have written const Blank = 2;  
I was in a bit of a rush.

---

<div class="post-metadata">

**Author:** ![gfvalvo](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/gfvalvo/32/1013044_2.png) [@gfvalvo](https://forum.arduino.cc/u/gfvalvo)\
**Post date:** [March 22, 2019, 4:28pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/9 "2019-03-22T16:28:56Z")

</div>

Try again:

```cpp
const uint8_t Blank = 2;

```

---

<div class="post-metadata">

**Author:** ![Ken\_F](https://avatars.discourse-cdn.com/v4/letter/k/848f3c/32.png) [@Ken\_F](https://forum.arduino.cc/u/Ken_F)\
**Post date:** [March 22, 2019, 4:46pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/10 "2019-03-22T16:46:36Z")

</div>

Thanks for the reply gfvalvo, I think, but posting just a line of code with no explanation just leaves me in the dark. How about so incite into what you are trying to tell me please?

MorganS, I understand why the second println returned 4 but I'm unclear on the value of "#define THREE 1 + 2".  
Also why did say I forgot the compiler can check the type of the variable?  
"The advantage of the const declaration is the compiler can check the type of the variable. (Which you forgot.)"

---

<div class="post-metadata">

**Author:** ![gfvalvo](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/gfvalvo/32/1013044_2.png) [@gfvalvo](https://forum.arduino.cc/u/gfvalvo)\
**Post date:** [March 22, 2019, 4:53pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/11 "2019-03-22T16:53:13Z")

</div>

> Ken\_F:  
> How about so incite into what you are trying to tell me please?

You need to supply a TYPE for the variable, not just a name and a value -- i.e. 'int', 'unsigned long', 'uint32\_t', 'float', 'double', 'in16\_t', etc, etc, etc.

---

<div class="post-metadata">

**Author:** ![Ken\_F](https://avatars.discourse-cdn.com/v4/letter/k/848f3c/32.png) [@Ken\_F](https://forum.arduino.cc/u/Ken_F)\
**Post date:** [March 22, 2019, 5:13pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/12 "2019-03-22T17:13:54Z")

</div>

Thanks gfvalvo, I don't know where my head was at when I typed that, but I do know that. The initial example was just fyi and not of crucial importance to the general question.

So the bottom line as I see it is use "const" instead of "#define" to prevent the names from changing value.

---

<div class="post-metadata">

**Author:** ![J-M-L](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/j-m-l/32/766245_2.png) [@J-M-L](https://forum.arduino.cc/u/J-M-L)\
**Post date:** [March 22, 2019, 6:17pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/13 "2019-03-22T18:17:49Z")

</div>

kind-of... bottom line is that they are two different things :) and `#define` somewhat something of the past for constants (due to inline and compiler optimization techniques);

# directives are better suited for pre-processor stuff

Strongly typing variables and constants helps provide cues to the compiler which can warn you if you do something stupid later on - including changing values or overflow in maths etc

---

<div class="post-metadata">

**Author:** ![Ken\_F](https://avatars.discourse-cdn.com/v4/letter/k/848f3c/32.png) [@Ken\_F](https://forum.arduino.cc/u/Ken_F)\
**Post date:** [March 22, 2019, 6:52pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/14 "2019-03-22T18:52:26Z")

</div>

Thanks J-M-L, but you're talking over my head with,

# directives are better suited for pre-processor stuff

Strongly typing variables and constants helps provide cues to the compiler which can warn you if you do something stupid later on - including changing values or overflow in maths etc

I have no idea what #directives, or pre-processor stuff is or what you mean by "Strongly typing"

---

<div class="post-metadata">

**Author:** ![Danois90](https://avatars.discourse-cdn.com/v4/letter/d/50afbb/32.png) [@Danois90](https://forum.arduino.cc/u/Danois90)\
**Post date:** [March 22, 2019, 7:06pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/15 "2019-03-22T19:06:12Z")

</div>

The pre-processor is what makes the source code ready for compiling. Strongly typing means that you, as the programmer, instruct the compiler to use exactly the data types you want. Look at the following snippet:

```cpp
#define PIN_NUMBER 3
...
pinMode(PIN_NUMBER, OUTPUT);
digitalWrite(PIN_NUMBER, HIGH);
digitalWrite(PIN_NUMBER, LOW);

```

The pre-processor will convert the code and feed the following to the compiler:

```cpp
pinMode(3, OUTPUT);
digitalWrite(3, HIGH);
digitalWrite(3, LOW);

```

As you can see, "PIN\_NUMBER" does no longer exist, only the value it defines does. Since "int" is the default data type, "3" may occupy 2 bytes in memory because it is un-typed. Now, lets try that with "strong typing":

```cpp
const uint8_t PIN_NUMBER = 3;
...
pinMode(PIN_NUMBER, OUTPUT);
digitalWrite(PIN_NUMBER, HIGH);
digitalWrite(PIN_NUMBER, LOW);

```

In this example the pre-processor will not modify anything. "PIN\_NUMBER" will exist at compile time and it will occupy exactely one unsigned byte - because you coded it like that.

---

<div class="post-metadata">

**Author:** ![RayLivingston](https://avatars.discourse-cdn.com/v4/letter/r/b5ac83/32.png) [@RayLivingston](https://forum.arduino.cc/u/RayLivingston)\
**Post date:** [March 22, 2019, 7:07pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/16 "2019-03-22T19:07:10Z")

</div>

> J-M-L:  
> `#define` somewhat something of the past for constants

#define is used for one helluva lot more than simply defining constants.  
Just one, absolutely trivial, example:

```arduino
#define getmax(a,b) ((a)>(b)?(a):(b))

```

And, of course, it can be abused to within an inch of its life. This is ALL a single #define. Anyone who does something like this should be taken out and shot, but it IS valid code, and WILL work.

```arduino
#define DECLARE_MODIFICATION_REQUEST_PACKET( T )                                                \
namespace NameSpace                                                                     \
{                                                                                       \
                                                                                        \
class T##ElementModificationRequestPacket;                                                          \
}                                                                                       \
                                                                                        \
DECLARE_STREAMING_TEMPLATES( IMPEXP_COMMON_TEMPLATE_DECLARE, NameSpace::ElementModificationRequestPacket<T>, OtherNameSpace::NetPacketBase )    \
DLLIMPEXP_COMMON_TEMPLATE_DECLARE( NameSpace::ElementModificationRequestPacket<T> )     \
DECLARE_AUTOGENERATION_TEMPLATES( DLLIMPEXP_COMMON_TEMPLATE_DECLARE, NameSpace::T##ModificationRequestPacket, NameSpace::ElementModificationRequestPacket<T> )      \
                                                                                        \
namespace NameSpace {                                                                   \
class DLLIMPEXP_COMMON T##ModificationRequestPacket : public ElementModificationRequestPacket<T>\
{                                                                                       \
public:                                                                                 \
    T##ModificationRequestPacket( NetBase * pParent )                                   \
    : ElementModificationRequestPacket<T>( pParent ), m_Gen() {}                            \
                                                                                        \
    T##ModificationRequestPacket( NetBase * pParent,                                    \
                            Action          eAction,                                    \
                            const T &   rT )                                            \
    : ElementModificationRequestPacket<T>( pParent, eAction, rT ), m_Gen() {}               \
                                                                                        \
    T##ModificationRequestPacket( const T##ModificationRequestPacket & rhs )                        \
    : ElementModificationRequestPacket<T>( rhs ), m_Gen() {}                                \
                                                                                        \
    virtual                     ~T##ModificationRequestPacket( void ) {}                        \
                                                                                        \
    virtual Uint32          GetPacketTypeID( void ) const                           \
    {                                                                                   \
        return Net::T##_Modification_REQUEST_PACKET;                                        \
    }                                                                                   \
                                                                                        \
    virtual OtherNameSpace::ClassID GetClassID ( void ) const                           \
    {                                                                                   \
        return OtherNameSpace::NetBase::GenerateHeader( OtherNameSpace::ID__LICENSING,  \
                                                         Net::T##_Modification_REQUEST_PACKET );    \
    }                                                                                   \
                                                                                        \
    virtual T##ModificationRequestPacket * Create( void ) const                             \
    { return new T##ModificationRequestPacket( m_pParent ); }                                   \
                                                                                        \
    T##ModificationRequestPacket() {}                                                           \
                                                                                        \
protected:                                                                              \
    OtherNameSpace::ObjectAutogeneration<T##ModificationRequestPacket> m_Gen;                       \
                                                                                        \
    friend class OtherNameSpace::StreamingBase::StreamingClassInfoT<T##ModificationRequestPacket >;                     \
    OtherNameSpace::StreamingBase::Streaming<T##ModificationRequestPacket, ElementModificationRequestPacket<T> >    m_Stream;   \
                                                                                        \
};                                                                                      \
}                                                                                       \
DLLIMPEXP_COMMON_TEMPLATE_DECLARE( ThirdNameSpace::ListenerBase<const NameSpace::T##ModificationRequestPacket> )            \
DLLIMPEXP_COMMON_TEMPLATE_DECLARE( ThirdNameSpace::BroadcasterT<const NameSpace::T##ModificationRequestPacket> )            \
typedef  ThirdNameSpace::BroadcasterT<const T##ModificationRequestPacket>  T##ModifiedBroadcaster;

```

Regards,  
Ray L.

---

<div class="post-metadata">

**Author:** ![J-M-L](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/j-m-l/32/766245_2.png) [@J-M-L](https://forum.arduino.cc/u/J-M-L)\
**Post date:** [March 22, 2019, 7:09pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/17 "2019-03-22T19:09:23Z")

</div>

Read about [Preprocessor directives](http://www.cplusplus.com/doc/tutorial/preprocessor/)

for the other, I actualy did not mean to use "strong" in the programing language context (read [this](http://wiki.c2.com/?StronglyTyped)) just meant that when you do a define, the implicit type (int, signed int, long, char etc) is attached to the value whereas if your provide a type, the value will be forced to conform to that type....

but no big deal at this stage, focus on the basics 😉

---

<div class="post-metadata">

**Author:** ![J-M-L](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/j-m-l/32/766245_2.png) [@J-M-L](https://forum.arduino.cc/u/J-M-L)\
**Post date:** [March 22, 2019, 7:12pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/18 "2019-03-22T19:12:35Z")

</div>

> RayLivingston:  
> #define is used for one helluva lot more than simply defining constants.

that was my point when I wrote " **for** constants" --\> For constant or simple function, it's obsolete in my opinion (use const or inline) but it has other legit (or far fetched) use cases

---

<div class="post-metadata">

**Author:** ![Ken\_F](https://avatars.discourse-cdn.com/v4/letter/k/848f3c/32.png) [@Ken\_F](https://forum.arduino.cc/u/Ken_F)\
**Post date:** [March 22, 2019, 10:29pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/19 "2019-03-22T22:29:39Z")

</div>

Thanks Danois90 that was very informative. I might even understand it. I appreciate you taking the time. If I understand you correctly, using #define IS NOT strong typing because it uses the default data type, but by defining a "const" variable as an 8-bit unsigned integer (const uint8\_t) you are telling the compiler what to use and not letting the pre-processor make that default determination. How close am I?

---

<div class="post-metadata">

**Author:** ![RayLivingston](https://avatars.discourse-cdn.com/v4/letter/r/b5ac83/32.png) [@RayLivingston](https://forum.arduino.cc/u/RayLivingston)\
**Post date:** [March 22, 2019, 10:42pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/20 "2019-03-22T22:42:53Z")

</div>

> Ken\_F:  
> Thanks Danois90 that was very informative. I might even understand it. I appreciate you taking the time. If I understand you correctly, using #define IS NOT strong typing because it uses the default data type, but by defining a "const" variable as an 8-bit unsigned integer (const uint8\_t) you are telling the compiler what to use and not letting the pre-processor make that default determination. How close am I?

The "type" of an expression defined using #define is a function of where/how the #define is actually used. A #define HAS NO TYPE, because it is NOT a variable declaration. It defines a literal string.

```arduino
#define XYZZY 32
int8_t myInt8 = XYZZY;  //myInt8 is an 8-bit signed value, with value 32
int16_t myInt16 = XYZZY;  //myInt is a 16-bit signed value, with value 32

```

```arduino
#define XYZZY (255)
uint8_t myuInt8 = XYZZY;  //myuInt8 is an 8-bit UN-signed value, with value 255
int8_t myInt8 = XYZZY;  //myInt8 is an 8-bit signed value, with value -1
int16_t myInt16 = XYZZY;  //myInt is a 16-bit signed value, with value 255

```

Regards,  
Ray L.

[Next page](https://forum.arduino.cc/t/define-vs-const/581308.md?page=2)
