I have a lot of named references to memory locations to in my code, and I'm curious if it would be wiser to use #define instead of static const to define them.
This is what I have:
static const word EPROM = 0xB600; //EEPROM Location
static const word EXTRAM2 = 0xB800; //EXTRAM Location
static const word LCD_CTL = 0x3000; //Control register of LCD
static const word LCD_DATA = 0x3001; //Data register of LCD
static const word HIRAM = 0xBFFF; //Highest address for 32k * 8 RAM
I know static const is the preferred method, but I have a lot of these and thought #define would be better as it is a direct substitution and won't eat up memory.
In C++, the compiler treats a 'const int a = value' similarly to #define (other than const int being properly scoped). You can use it as an array bound for instance.
If you were using C, instead of the C++ that the IDE uses, then const int's at the global level do allocate space, and when you use the value, it loads it from memory. You can't use it as an array bound without the compiler using variable sized arrays.
If you use #define, the compiler does a textual substitution anytime it sees the name, so you can't use the same name for instance as a member of a structure.
On systems with real source level debuggers, const int values are more often available in the debugger for use in expressions. However, this isn't an issue for Arduino, where debugging consists of blinky lights or Serial.println's.
So "const int foo = value" won't result in memory being allocated for "foo" when it's compiled in the Arduino IDE?
would "static const int foo = value" be the same then?
If I used "#define TempRead 20", then later on in my code had "int TempReading = 1;", would it get converted to "20ing = 1;" by the preprocessor?
Const values are explicitly typed, and #defined literal values are not. Const values have a defined scope and namespace, and #defined literal values do not. Before const definitions were supported, using #defines for the literal values was the best option. Now that const definitions are available, there is no good reason to use #defines for constants. Const values do the same job, better.
MichaelMeissner:
However, this isn't an issue for Arduino, where debugging consists of blinky lights or Serial.println's.
How much easier it would be to find our coding errors if we could 'run to' a point in the code and then 'step' from there, like real debuggers allow you to do.
A "real debugger" is another process on the same computer. When you have developed an operating system for the Arduino that supports multiple processes, then you can think about running a "real debugger" on the Arduino.
PaulS:
A "real debugger" is another process on the same computer. When you have developed an operating system for the Arduino that supports multiple processes, then you can think about running a "real debugger" on the Arduino.
Let us know when it is ready.
GDB supports various embedded platforms by linking a stub program in with the user's program. Typically this stub is fairly small, and most of the smarts are on the host side. It can also be done by simulating the target chip. For example, it looks like there was a WinAVR that supported AVR chips via GDB, though the last release was in 2009. CrossPack for AVR that runs on the Mac looks like it is maintained and more recent. So, it can be done, it is just nobody has stepped up to do the work for the Arduino.
Remember, const isn't always a compile time constant.
If you really have constant values, and and want to guarantee they are compile time constants: simply use an enum.
Then the values aren't cast if the datatypes don't match, they will be natural type of the L-Value.
pYro_65:
Remember, const isn't always a compile time constant.
Oh?
I have a lot of named references to memory locations to in my code, and I'm curious if it would be wiser to use #define instead of static const to define them.
I would just use const rather than "static const". The use of "static" has an effect (if any) other than what you intend, which is to not make the constant exported to the linker.
I prefer the use of const variables because defines are just a text substitution, whereas const variables are typed. Also the error messages which arise from them (when they happen) are less confusing.
We have shown before that const "variables" (is there really such a thing?) do not take up memory.
Thanks for all the info, I've left it consts (which can be changed via pointers AFAIK). We've kind of diverted a bit, but is there a fundamental difference between declaring something a word, vs. an unsigned int vs. a uint16? I just picked word because I'm doing a lot of stuff with bytes and double bytes and think of it that way. Plus it's the shortest name to type :).
PaulS:
A "real debugger" is another process on the same computer. When you have developed an operating system for the Arduino that supports multiple processes, then you can think about running a "real debugger" on the Arduino.
Let us know when it is ready.
I never claimed it was possible, only that it's desirable.
MichaelMeissner:
So, it can be done, it is just nobody has stepped up to do the work for the Arduino.
I'm not convinced it is useful, on a platform where timing is often the issue. Things like programs hanging because they do serial prints inside an ISR are very timing-related. Once you stop the code at a breakpoint to look at things, they are likely to change (imagine looking at TCNT1 with a debugger).
Plus there are resource issues, simply adding debugging code may make a problem appear, or indeed, go away.
For calculation issues (eg. did a number get rounded or not?) some serial prints often help. For timing issues, like did an ISR fire when you expect it, blinking LEDs (and checking timing with a logic analyzer) is pretty unobtrusive.