macro vs. const.....

I have seen some sketches that use (example) #define LEDPIN 10 to refer to digital/analog pins and I have also seen some that use (example) const int ledpin = 10; or just int ledpin = 10;

What is the difference between the two? Why do I want to use one way over the other?

Bcarroll: I have seen some sketches that use (example) #define LEDPIN 10 to refer to digital/analog pins and I have also seen some that use (example) const int ledpin = 10; or just int ledpin = 10;

What is the difference between the two? Why do I want to use one way over the other?

The define is a macro that only 'lives' during compilation time where anywhere in the sketch source there appears a LEDPIN the compiler with substitute the value of 10.

The const defines a real read only variable that will remain in memory as the sketch is running and any reference to ledpin will equate to the number 10.

Therefore the macro can in theory save you run time SRAM space which can be useful at times. Simple macros I can live with, but some of the macros the software gurus around here come up with gives sever headaches. ;)

At least that is this hardware guys understanding of it and I can always stand being corrected by the software gods that lurk around here.

Lefty

There was a quite lengthy thread on the subject last month: http://arduino.cc/forum/index.php/topic,86800.0.html

The hardware guy almost got it right 1. Unless you take the address of a const, the compiler optimizes it away. In other words, in the majority of cases const and #define are interchangeable. Use whichever you prefer.

Don’t use the last case. It generates considerably more code and wastes precious SRAM.

1 Which does not imply I’m a “software god”.

I prefer

define LEDPIN 10

to the others because it's louder. :grin:

Apparently my search criteria was too narrow...

Thanks dxw00d! http://arduino.cc/forum/index.php/topic,86800.0.html provides all the information I was looking for.

Looks like I'll be sticking with the const int ledpin = 10; usage...

Don't use the last case. It generates considerably more code and wastes precious SRAM

And also doesn't prevent inadvertently changing a "const" value, which can causing very sublte bugs...

Use of const is not going to "waste space." The advantage of const is that it provides type safety. You can do this with #defines, but is generally not done. And if you're providing type safety with #defines, you should probably be using const anyways as its easier to read and more concise. Use of defines also can have side effects for non-trivial use; sometimes even result in the wrong code being generated. Which is why the common use case of defines have long been deprecated by C++'s use of const.

Best practices and official recommendation is to use const where it makes sense and only use define where const breaks down. For the majority of Arduino users, it means const should be the preferred mechanism. Clearly that's not the case.

Now, some more detail. The compiler isn't JUST a compiler. Modern compilers have what is called a pre-processor. The pre-processor does several things. One of these things is to physically substitute defines with each occurrence before the compiler ever sees the code.

So when you have:

#define BAR 1
int foo( void ) {
return BAR ;
}

The compiler ever only sees:

int foo( void ) {
  return 1 ;
}

Likewise, if you use:

const int BAR = 1 ;
int foo( void ) {
  return BAR ;
}

The compiler actually does see a variable named BAR. And that's what scares people into believing it wastes space. The deal is, the compiler is very good at literal substitution. In fact, its one of those trivial things which is almost always first to be implemented in even ancient compilers. And so, the compiler is smart enough to not only realize how the variable BAR is used, but to see its strictly only ever used as a read-only, constant value. And so, the code the compiler generates is semantically the same as:

int foo( void ) {
  return 1 ;
}

Notice its the same? The compiler will not waist space on the variable because it will effectively be compiled out; having been literally replaced. Even in the assembly, you should see that it does something like load the literal value 0x0001 into a register(s), rather than perform a memory lookup. Meaning, the generated instruction set will see it as a literal value rather than a variable to be looked up in memory. And since there is no look up in memory, the variable is compiled out. Meaning, it never existed in the compiled output.

Now then, use of const also provides additional benefits over that of define, which is type safety. You see, in the define above, the compiler just infers a type for the literal of '1'. This can create problems. Though generally not for the simple case given above. Whereas use of the const declaration, specifically informs the compiler the type of the variable thereby preventing the compiler from being forced to make wild assumptions which may result in the wrong assumption being made. To avoid this inference of the compiler, you would be doing something like:

#define BAR ((int)1)

Which as you can see, is comparable to:

const int BAR = 1 ;

Long story short, const should be preferred over define.

Use of const is not going to "waste space."

The "waste space" comment referred to the non-const case.

I was speaking to the generalized complaint which is often associated with this topic, not to a specific comment made above. The common concern is one of size. Such concerns were previously raised as well as touched on here. As such, I addressed size concerns. Given the limited size of available flash and ram, it would seem like the obvious concern to address.

Had I been referring to that comment, I would have quoted it. I wasn't and I didn't. No offense was intended by my seemingly poor choice of words. The quotes were air quotes given its a recurring concern. I likely used those words simply because I had just read them and that phrasing was in my head.

I'll also add, use of const does bring yet more additional benefits. Some of which have been mentioned above. Use of const allows for potential compiler optimization and helps protect against wayward programmers; meaning unintentional change.

So for example you have something like the following.

const int importantVarX = 1 ;
int importantVarXY = 2 ;
int foo( void ) {
  importantVarX++ ;
  return importantVarXY ;
}

In the above, the importantVarXY was supposed to be incremented. If the read-only variable has not been declared read-only (via const), the code above would have compiled and silently created a bug. In the case above with variables which are closely named, this frequently creates a category of bug which is hard to track down because the brain reads what it wants to see rather than what is actually there.

Should you compile the above, you should see a nice error like:

error: assignment of read-only variable ‘importantVarX’

So given the above, we equipped the compiler to save us from ourselves. And in return for our efforts, the compiler did just that.

tuxduino:

Don't use the last case. It generates considerably more code and wastes precious SRAM

And also doesn't prevent inadvertently changing a "const" value, which can causing very sublte bugs...

Unless you need to.

Don't forget that sometimes changing a pin is a good idea. For example, if you have three LEDs that show activity. For example, if you have a stop light, you could define three pins

const int go = 4; const int goReallyFast = 5; const int slamOnBrakes = 6;

then use an if-then-else to pick which one of those three pins to turn on or off.

Or you could use a single variable --

define GO_PIN 4

define WARNING_PIN 5

define STOP_PIN 6

int currentPin = 4;

Then instead of a giant if-then-else, you write

int previousPin = currentPin; digitalWrite(nextPin, HIGH); digitalWrite(currentPin, LOW); currentPin = previousPin;

Don't just think in terms of "code". "Data" is also part of a program.

I guess because of the way I was introduced to PICs some years ago I always assume that for a pin beign either input or output is a sort of hardware-only thing. So you configure it in software in one way or the other based on the circuit, and never change that.

Your technique is indeed interesting.