Why do people use #define insted of int/char/float ?

I don't understad why people declaring values with #define?

If i want do declare an int value of 4 i write int value = 4; and not #define value 4
What the difference?

value might take up 2 bytes on the stack which uses up limited RAM.

The number define might only take up Flash space and be directly loaded into the chip register.

I say "might" because gcc is a pretty smart optimizing compiler, so details matter.

const int value = 4; would be better.

But your method is inefficient, and is not correct in places you are expecting a constant. You need to use const.

Basically #define is a textual substitution that occurs early in the logical stages of compilation. So that if you do:

#define FOO 1
    // ...
if (a == FOO) { ... }

The main part of the compiler actually sees:

if (a == 1) { ... }

Because it is a preprocessing step, the #define's are not scoped like normal identifiers. However, because it is a handled in the processing phases, you can use #define'd names in #if and other #-type tests.

If you use const int to declare that value, that does created a scoped constant of the appropriate type. For the most part, either #define or using const will generate the same code in a C++ context. In C++ (but not C), a value declared const with constant value, the compiler can optimize the value, and eliminate the variable. In a pure C context, the rules for const are different, and the compiler will generally need to create a variable for the constant. However, since Arduino uses C++ by default, you only need to know these picky rules if you to go to other projects.

People who are more familiar with the C language tend to use #define. People who are more familiar with the C++ language will tend to use const int type declarations.

If you do not include const, the compiler will need to create a variable to hold the constant. If it is at file scope (outside of a function), this will entail creating a global variable to store the constant. Then all uses of the constant will load from that variable. If you declare the variable inside of a function, the optimizer might eliminate the variable, but it is a good habit to always use const where you can.

1 Like

#define's are handled by the pre-processor and are purely textual substitution at
compile time only. Nothing is present at runtime.

If you declare a variable it will need storage at runtime (unless the compiler
succeeds in optimizing the declaration away).

If you are declaring a constant it pays to declare it const, then the compiler is
let in on that fact.

const int RED = 1 ;

The compiler will both be able to report assignments to RED as an error, and probably
succeed in optimizing the declaration away if its not needed.

BTW the prefered way to do a #define of a value is to have parentheses around
it to prevent any mis-parsing of the substituted code:

#define RED (1)

This really matters if you define constants in terms of others:

#define RED (1)
#define GREEN (RED+1)
#define BLUE (GREEN+1)

This means if you go

  int foo = BLUE * 256 + RED ;

You get no surprises due to operator precedence (* binds tighter than +)

4 just needs a byte.
byte value = 4;

Most things I use are variables, so const & #define are no help.
I could see them for assigning pin definitions if they will not change, like SS for hardware devices.
I have never been so tight on SRAM that I couldn't make all the pin assignments & variables I wanted global and either unsigned long, int, byte, or sometimes char.

It seems that many folks use int when byte would do.

So you say that i don't need to use #define if i want to send a value to the preprocessor or something like that?

Exemple:
I can write this

#include 
#include "DS18S20.h"
#include "DS18B20.h"
#include "OneWireDefs.h"

//#define THERMOMETER DS18S20
#define THERMOMETER DS18B20

int main()
{
    //          device( crcOn, useAddress, parasitic, mbed pin )
    THERMOMETER device(true, true, false, p25);
    
    while (!device.initialize());    // keep calling until it works
    
    while (true)
    {
        // changing the resolutions only affects the DS18B20. The DS18S20 is fixed.
        device.setResolution(nineBit);
        device.readTemperature(); 
        wait(5);
        device.setResolution(tenBit);
        device.readTemperature(); 
        wait(5);
        device.setResolution(elevenBit);
        device.readTemperature(); 
        wait(5);
        device.setResolution(twelveBit);
        device.readTemperature(); 
        wait(5);
    }
     
    return EXIT_SUCCESS;
}

and it will works exactly the same as this one?

#include 
#include "DS18S20.h"
#include "DS18B20.h"
#include "OneWireDefs.h"

//#define THERMOMETER DS18S20
char THERMOMETER[20] = "DS18B20";

int main()
{
    //          device( crcOn, useAddress, parasitic, mbed pin )
    THERMOMETER device(true, true, false, p25);
    
    while (!device.initialize());    // keep calling until it works
    
    while (true)
    {
        // changing the resolutions only affects the DS18B20. The DS18S20 is fixed.
        device.setResolution(nineBit);
        device.readTemperature(); 
        wait(5);
        device.setResolution(tenBit);
        device.readTemperature(); 
        wait(5);
        device.setResolution(elevenBit);
        device.readTemperature(); 
        wait(5);
        device.setResolution(twelveBit);
        device.readTemperature(); 
        wait(5);
    }
     
    return EXIT_SUCCESS;
}

you say that i don't need to use #define if i want to send a value to the preprocessor or something like that?

No. If you want a value that is accessible to the preprocessor, you must use #define.
if you want a value that is accessible to the compiler, you can use either a #define or a variable.

THERMOMETER device(true, true, false, p25);

This is a good example of where THERMOMETER must be something #defined'ed in the preprocessor. The C language does not have the ability to use a variable as a type specifier.

Although you might want to do something like:
//typedef DS18S20 THERMOMETER;
typedef DS18B20 THERMOMETER;
Picking that over #define would be a whole different discussion.

CrossRoads:
It seems that many folks use int when byte would do.

my (admittedly limited) understanding was that both byte and int are mapped to uint8_t, so I'd assume they take the same ammount of resources?

scrumfled:
my (admittedly limited) understanding was that both byte and int are mapped to uint8_t, so I'd assume they take the same ammount of resources?

No, on AVR systems, int is the same size as int16_t or short, i.e. 16-bits. On ARM systems like the Due and Teensy 3.0, an int is the same size as int32_t, i.e. 32-bits.

So if a variable will only hold values 0..255, then use uint8_t. If it will hold values -128..127, then use int8_t, etc.

persson121:
I don't understad why people declaring values with #define?

Habit, and ignorance.

PeterH:

persson121:
I don't understad why people declaring values with #define?

Habit, and ignorance.

Now wait a min, while I don't normally use #defines, it's been explained to me that using a define to assign a name to a arduino pin number does save memory over defining it as a global variable.

#define solenoidPin 3
does not consume/utilize SRAM memory
int solenoidPin = 3;
does consume/utilize SRAM memory

So saying it's just habit or even worst ignorance, seems rather well ignorant to me. Or am I missing something?

#define solenoidPin 3
does not consume/utilize SRAM memory
int solenoidPin = 3;
does consume/utilize SRAM memory

Correct. But,

const int solenoidPin = 3;  // probably does not consume memory
static const int solenoidPin = 3;  // almost certainly does not consume memory

(of course, this introduces a couple of "mysterious" and relative complex concepts/keywords that "we" sort-of feel like an arduino beginner shouldn't need to understand.)

westfw:

#define solenoidPin 3

does not consume/utilize SRAM memory
int solenoidPin = 3;
does consume/utilize SRAM memory



Correct. But, 

const int solenoidPin = 3;  // probably does not consume memory
static const int solenoidPin = 3;  // almost certainly does not consume memory



(of course, this introduces a couple of "mysterious" and relative complex concepts/keywords that "we" sort-of feel like an arduino beginner shouldn't need to understand.)

I'll settle for "correct" :wink:

OK. I guess "#define foo 4" never defines storage (or consumes memory) (because "foo" is never actually seen by the compiler, while "xxx int foo = 4" relies on compiler optimization (which may be dependent on particular vendor and version of the compiler) to notice that the storage defined can be eliminated.

Sometime down the road const may be a better choice because a #define is not accessible by a debugger. After the textual pass by the preprocessor, the #define is gone; no variable exists in the symbol table. But then, there's no debugger in the IDE, either.