# \#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:** 2

<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 23, 2019, 1:58am UTC](https://forum.arduino.cc/t/define-vs-const/581308/21 "2019-03-23T01:58:39Z")

</div>

And it is the compiler which worries about types. The preprocessor is a text processor which doesn't even understand C.

---

<div class="post-metadata">

**Author:** ![econjack](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/econjack/32/1290082_2.png) [@econjack](https://forum.arduino.cc/u/econjack)\
**Post date:** [March 23, 2019, 2:49am UTC](https://forum.arduino.cc/t/define-vs-const/581308/22 "2019-03-23T02:49:35Z")

</div>

> Danois90:  
> 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! 😉

Anything can be dangerous if you don't understand what you're doing when you use it. I'm not sure what you mean by #define's being overwritten. Also, the fact that #define's are "typeless" can be an advantage. The macro:

#define ELEMENTS(x) (sizeof(x) / sizeof(x[0]))

will return the number of elements in any aggregate date type, which is an advantage, not a disadvantage.

---

<div class="post-metadata">

**Author:** ![Jiggy-Ninja](https://avatars.discourse-cdn.com/v4/letter/j/8edcca/32.png) [@Jiggy-Ninja](https://forum.arduino.cc/u/Jiggy-Ninja)\
**Post date:** [March 23, 2019, 2:53am UTC](https://forum.arduino.cc/t/define-vs-const/581308/23 "2019-03-23T02:53:45Z")

</div>

> Ken\_F:  
> Is one better than the other? (faster, uses less memory. etc)

No.

---

<div class="post-metadata">

**Author:** ![jimLee](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/jimlee/32/214865_2.png) [@jimLee](https://forum.arduino.cc/u/jimLee)\
**Post date:** [March 23, 2019, 6:10am UTC](https://forum.arduino.cc/t/define-vs-const/581308/24 "2019-03-23T06:10:53Z")

</div>

Then if you get tired of typing Serial.println(...) stuff you can do..

#define out Serial.print  
#define outln Serial.println

I don't think you can do that with const.

You know.. I don't think I've ever actually used const.

-jim lee

---

<div class="post-metadata">

**Author:** ![luni64](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/luni64/32/651574_2.png) [@luni64](https://forum.arduino.cc/u/luni64)\
**Post date:** [March 23, 2019, 7:07am UTC](https://forum.arduino.cc/t/define-vs-const/581308/25 "2019-03-23T07:07:25Z")

</div>

You can not do that "with const", but of course you do not need a #define for it. The way you'd do that in c++ is

```cpp
//#define out Serial.print

template< typename T > void out( T data )
{   
   Serial.print(data);
}
 
void setup() 
{     
   out(5);  
  out(3.1415);
  //....
}

void loop() 
{
}

```

---

<div class="post-metadata">

**Author:** ![bidouilleelec](https://avatars.discourse-cdn.com/v4/letter/b/c5a1d2/32.png) [@bidouilleelec](https://forum.arduino.cc/u/bidouilleelec)\
**Post date:** [March 23, 2019, 7:34am UTC](https://forum.arduino.cc/t/define-vs-const/581308/26 "2019-03-23T07:34:23Z")

</div>

> RayLivingston:  
> ........
> 
> ```arduino
> #define XYZZY (255)
> 
> ```

int8\_t myuInt8 = XYZZY; &nbsp;//myuInt8 is an 8-bit UN-signed value, with value 255

> ```arduino
> 
> Regards,
> Ray L.
> 
> ```

"uint8\_t myuInt8 = XYZZY; //myuInt8 is an 8-bit UN-signed value, with value 255" ????

Regards,  
bidouilleelec

---

<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 23, 2019, 8:34am UTC](https://forum.arduino.cc/t/define-vs-const/581308/27 "2019-03-23T08:34:19Z")

</div>

Note also bad consequences of non typed constants when doing maths

```cpp
#define oneMillis 1000 // in microsec
#define oneSec (1000*oneMillis)
#define oneMin (60*oneSec)
#define oneHour (60*oneMin)
#define oneDay (24*oneHour)

```

seems at first sight safe because we used parenthesis to protect calculated results

Challenge is that none of the litterals are typed and thus the compiler will take the smaller integral (int or larger) representation that fits and you’ll overflow. Solution would be to add UL at the end of the litterals to force the compiler to know the type.

Contrast with typed constants

```cpp
const uint32_t oneMillis = 1000; // in microsec
const uint32_t oneSec = (1000*oneMillis);
const uint32_t oneMin = (60*oneSec);
const uint32_t oneHour = (60*oneMin);
const uint32_t oneDay = (24*oneHour);

```

because in the formulas there is an long unsigned int the compiler knows about due to the type of the constant, all will be fine.

---

<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 23, 2019, 11:34am UTC](https://forum.arduino.cc/t/define-vs-const/581308/28 "2019-03-23T11:34:11Z")

</div>

> luni64:  
> but of course you do not need a #define for it. The way you'd do that in c++ is

You don't need an ugly C++ template either:

```arduino
Stream &out = Serial;

void setup() {
  Serial.begin(115200);
  delay(1000);
  
  out.println("Hello World");
}

void loop() {
}

```

---

<div class="post-metadata">

**Author:** ![GolamMostafa](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/golammostafa/32/239011_2.png) [@GolamMostafa](https://forum.arduino.cc/u/GolamMostafa)\
**Post date:** [March 23, 2019, 11:51am UTC](https://forum.arduino.cc/t/define-vs-const/581308/29 "2019-03-23T11:51:06Z")

</div>

> Danois90:  
> 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.

Will the symbolic name PIN\_NUMBER be replaced by 00000011 (0x03) at run-time?

---

<div class="post-metadata">

**Author:** ![oqibidipo](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/oqibidipo/32/221794_2.png) [@oqibidipo](https://forum.arduino.cc/u/oqibidipo)\
**Post date:** [March 23, 2019, 12:02pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/30 "2019-03-23T12:02:12Z")

</div>

> gfvalvo:  
> You don't need an ugly C++ template either:
> 
> ```arduino
> Stream &out = Serial;
> 
> ```

···  
&nbsp;out.println("Hello World");

> ```arduino
> 
> ```

That's not the same, you can't do

```arduino
out("blabbediblaa....");

```

---

<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 23, 2019, 12:05pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/31 "2019-03-23T12:05:02Z")

</div>

> GolamMostafa:  
> Will the symbolic name PIN\_NUMBER be replaced by 00000011 (0x03) at run-time?

No, constants are evaluated at compile time, #defines are evaluated before compile time.

And by "overwritten" (redeclared is probably the right term) i mean that the value of a define may change:

```arduino
#define MAX_PWM 100

void a() { analogWrite(PIN, MAX_PWM); }

#define MAX_PWM 200

void b() { analogWrite(PIN, MAX_PWM); }

void loop()
{
  a();
  b();
}

```

The code is valid, but what do we get? This behaviour may be especially problematic if two libraries/includes exposes the same define with different values.

---

<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 23, 2019, 1:19pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/32 "2019-03-23T13:19:41Z")

</div>

constant (wether defines as such or litterals or #define replaced by litterals) will be going through the optimizer and all the ones fitting on one byte very likely replaced by their value directly in the assembly code

So when you define a PIN number through a const byte or a#define you end up with no extra RAM allocated - just flash space and direct value access in binary rather than an indirection or loading the variable content from memory into a register

---

<div class="post-metadata">

**Author:** ![luni64](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/luni64/32/651574_2.png) [@luni64](https://forum.arduino.cc/u/luni64)\
**Post date:** [March 23, 2019, 2:25pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/33 "2019-03-23T14:25:19Z")

</div>

> Danois90:  
> No, constants are evaluated at compile time ...

Hm, not necessarily. Example:

```arduino
void foo(int i)
{
    const int s = i *10;
    // do something with s...
}

```

is perfectly valid but obviously the compiler can not know the value of s at compile time. If you want to make sure that the value is known at compile time you should use constexpr instead:

```arduino
void foo(int i)
{
    constexpr int s = i *10;
    // do something with s...
}

```

This will generate a compiler error since s is not known at compile time.

So, if you want to replace the ancient #defines, it is better to use constexpr instead of const.

---

<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 23, 2019, 3:15pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/34 "2019-03-23T15:15:18Z")

</div>

You are right - was talking global and those which the optimizer can identify at compile time - not generic use of const

Note that in your case the optimizer might still decide to not allocate the memory and just dump the formula where you use it.

---

<div class="post-metadata">

**Author:** ![luni64](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/luni64/32/651574_2.png) [@luni64](https://forum.arduino.cc/u/luni64)\
**Post date:** [March 23, 2019, 3:29pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/35 "2019-03-23T15:29:38Z")

</div>

BTW: You can also do much more interesting things with constexpr (which will definitely not work with #defines)

E.g. if you declare a function constexpr then the compiler tries to evaluate the function at compile time.  
Here an example of the gaussian sum: i.e. 1+2+3 +... +n; For n= 100 this gives 5050 (see [http://mathcentral.uregina.ca/qq/database/qq.02.06/jo1.html](http://http://mathcentral.uregina.ca/qq/database/qq.02.06/jo1.html))

You can write:

```cpp
constexpr unsigned gauss(unsigned n)
{
  return n == 0 ? 0 : n+ gauss(n-1);
}

void setup() 
{      
    constexpr unsigned sum = gauss(100);
}

void loop() {
  // put your main code here, to run repeatedly:
}

```

And the compiler will calculate that for you, no runtime code generated, just the result. You can use that result wherever a constant is required.

You can check the generated assembly with the compiler explorer here: [Compiler Explorer](https://godbolt.org/z/TFREAX) Remove the constexpr from the first line and compare the result 🙂

PS: Unfortunately the compiler which is currently used by the Arduino IDE is still using std=c++11. Thus constexpr functions are limited to very simple constructs like shown above. Newer language standards allows much more freedom for constexpr functions.

---

<div class="post-metadata">

**Author:** ![Jiggy-Ninja](https://avatars.discourse-cdn.com/v4/letter/j/8edcca/32.png) [@Jiggy-Ninja](https://forum.arduino.cc/u/Jiggy-Ninja)\
**Post date:** [March 25, 2019, 1:49am UTC](https://forum.arduino.cc/t/define-vs-const/581308/36 "2019-03-25T01:49:16Z")

</div>

> luni64:  
> You can not do that "with const", but of course you do not need a #define for it. The way you'd do that in c++ is
> 
> ```arduino
> //#define out Serial.print
> 
> ```

template\< typename T \> void out( T data )  
{&nbsp;  
&nbsp; Serial.print(data);  
}

void setup()  
{&nbsp; &nbsp;  
&nbsp; out(5);&nbsp;  
&nbsp; out(3.1415);  
&nbsp; //....  
}

void loop()  
{  
}

> ```arduino
> 
> ```

> gfvalvo:  
> You don't need an ugly C++ template either:
> 
> ```arduino
> Stream &out = Serial;
> 
> ```

void setup() {  
&nbsp; Serial.begin(115200);  
&nbsp; delay(1000);  
&nbsp;  
&nbsp; out.println("Hello World");  
}

void loop() {  
}

> ```arduino
> 
> ```

#defines can let you do conditional compilation. I use this as a quick way to eliminate debug prints from my code.

```arduino
#ifndef NO_DEBUG
  #define DEBUG(x) Serial.println(x)
#else
  #define DEBUG(x)
#endif

```

You can DEBUG("whatever you want") wherever you would use a Serial.println for debugging purposes, and everything works just fine. Then, when your sketch is ready for deployment and you want to strip them all out, #define NO\_DEBUG. The DEBUG(x) macro will be defined to nothing, so all occurrences of it in the code (including its arguments!) vanish.

Edit: Also, it's a little known fact, but the print functions can take more than one argument. The template function shown in the first post will not work in all cases. You would need to use a template parameter pack for the function argument.

---

<div class="post-metadata">

**Author:** ![holmes4](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/holmes4/32/215302_2.png) [@holmes4](https://forum.arduino.cc/u/holmes4)\
**Post date:** [March 25, 2019, 1:59am UTC](https://forum.arduino.cc/t/define-vs-const/581308/37 "2019-03-25T01:59:13Z")

</div>

This is a total silly argument - high time this thread was locked.

Or even better deleted! It's far from the first on this topic.

Mark

---

<div class="post-metadata">

**Author:** ![jimLee](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/jimlee/32/214865_2.png) [@jimLee](https://forum.arduino.cc/u/jimLee)\
**Post date:** [March 25, 2019, 6:14am UTC](https://forum.arduino.cc/t/define-vs-const/581308/38 "2019-03-25T06:14:48Z")

</div>

If people post on it, it would seem to me they are interestd. Why shut it down?

I like that #define DEBUG(X) thing!

-jim lee

---

<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 25, 2019, 10:42am UTC](https://forum.arduino.cc/t/define-vs-const/581308/39 "2019-03-25T10:42:16Z")

</div>

> Jiggy-Ninja:  
> Edit: Also, it's a little known fact, but the print functions can take more than one argument. The template function shown in the first post will not work in all cases. You would need to use a template parameter pack for the function argument.

You can use variable arguments:

```arduino
//Will allow zero or more arguments:
#define PRINTLN(...) Serial.println( __VA_ARGS__ )

```

---

<div class="post-metadata">

**Author:** ![system](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/system/32/1140315_2.png) [@system](https://forum.arduino.cc/u/system)\
**Post date:** [May 5, 2021, 11:42pm UTC](https://forum.arduino.cc/t/define-vs-const/581308/40 "2021-05-05T23:42:56Z")

</div>

Closed on May 5, 2021, 11:42pm UTC



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