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)
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.
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?
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!
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.
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.)"
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.
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.
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
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"
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:
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":
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.
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:
#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.
for the other, I actualy did not mean to use "strong" in the programing language context (read this) 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
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
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?
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.
#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
#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