Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

A case for not using #define for constants in most languages.

Status
Not open for further replies.

3v0

Coop Build Coordinator
Forum Supporter
MPLABX is going to be a great tool in a few years. While fighting with it today I ran into some problems that reminded me of this.

We can write code like this

Code:
#define PEOPLE_MAX 666
...
int people[PEOPLE_MAX];
...
while (i<[PEOPLE_MAX])
....
After the text preprocessor does it magic the file sent to the compiler will contain something like this. I commented out PEOPLE_MAX because it does not survive past the preprocessor.
Code:
//#define PEOPLE_MAX 666
...
int people[666];
...
while (i<666)
....
I suggest a better version is this.
Code:
const unsigned int PeopleMax = 666;
...
int people[PeopleMax];
...
while (i < PeopleMax)
....

If you are thinking the 2nd version will use more memory you would be mistaken. In the first version the compiler creates a constant variable too. But it is on that is hidden from us.

In the 2nd version the constant PeopleMax is know to the compiler, debugger, and printf debug statments (for people not using debuggers).

Most compilers will not let you easily change the value of a constant.
Code:
PeopleMax=32;
generates the error
E:\Users\3v0...\main.c:50:Error [1102] cannot assign to 'const' modified object

#define is better used for condition compilation.
Code:
#define DEBUG_ME
#ifdef DEBUG_ME
printf("the value of PeopleMax: %d", PeopleMax);
#endif

// which will output
the value of PeopleMax: 666


The preprocessor is a great tool but we are better off not using it for constants.
 
very interesting post 3v0!!alot of people like me have no idea how the compiler does anything!!! realy useful to get a glimpse " behind the scenes" personaly i would love more of this kind of stuff (uhhuh yep,yes, was a hint :D)
 
There are some small down sides.

The first is that if you have two constants with the same value it will take twice the space as two defines with the same value.

The second is that not all languages/compilers allow "const int". I expect this is the case with most embedded languages/cross compilers.

Please do not get the idea that I am attempting to enforce this.


3v0
 
Last edited:
it dosnt come across as you attempting to enforce anything!!! just precise clear information. very helpful to people like me.
 
...
Code:
#define PEOPLE_MAX 666
...
int people[PEOPLE_MAX];
...
while (i<[PEOPLE_MAX])
....

Hi 3V0, I'm completely missing what the problem is? Is it because you used (i<[PEOPLE_MAX]) and not (i<PEOPLE_MAX) as would be normally done??
 
Try compiling,
Code:
#include <p18f1320.h>

#pragma config WDT = OFF, LVP = OFF, OSC = INTIO2, MCLRE = ON

const unsigned int PeopleMax = 6;

int people[PeopleMax];

void main(void){
char i;
    while (i < PeopleMax);
}

You get error,
C:\Projects\C18 1320\test.c:7:Error [1219] integer constant expected

Whereas,
Code:
#include <p18f1320.h>

#pragma config WDT = OFF, LVP = OFF, OSC = INTIO2, MCLRE = ON

#define PeopleMax 6

int people[PeopleMax];

void main(void){
char i;
    while (i < PeopleMax);
}
compiles fine.

Edit, if you rem out the array it then compiles. However, the const version stores the variable in ROM. This is what I wanted to test when I tried this.
Edit2, The const version also uses 6 more ROM locations than the #define one. I have no idea why.

Mike.
 
Last edited:
Try compiling,
Code:
#include <p18f1320.h>

#pragma config WDT = OFF, LVP = OFF, OSC = INTIO2, MCLRE = ON

const unsigned int PeopleMax = 6;

int people[PeopleMax];

void main(void){
char i;
    while (i < PeopleMax);
}

You get error,
C:\Projects\C18 1320\test.c:7:Error [1219] integer constant expected

Whereas,
Code:
#include <p18f1320.h>

#pragma config WDT = OFF, LVP = OFF, OSC = INTIO2, MCLRE = ON

#define PeopleMax 6

int people[PeopleMax];

void main(void){
char i;
    while (i < PeopleMax);
}
compiles fine.

Edit, if you rem out the array it then compiles. However, the const version stores the variable in ROM. This is what I wanted to test when I tried this.
Edit2, The const version also uses 6 more ROM locations than the #define one. I have no idea why.

Mike.

out of interest mike... the compiler you used was it the free non optimised version that used 6 more locations? if so does anyone know if the full optimised compiler would handle it the same way??? just a curiosity question.
 
@Mike

My bad for not testing the example:mad:

Yeah I discovered the same thing with switch case labels. It seems this is a limitation that has been fixed in more modern compilers. But given that we are looking at embedded compilers it is not unexpected.

Edit2, The const version also uses 6 more ROM locations than the #define one. I have no idea why.

I added several rom const vars in a C18 application with existing const vars. Adding more vars used the space needed only for the data itself. Tried up to 9 more ints, bytes use one memory location. This is with all optimization off.

The 6 bytes may be a one time overhead of maybe there is a min allocation of 8 bytes. I am less concerned about memory then I used to be.

Fun stuff.
 
Constants have the advantage that they are just normal variables, therefore are declared (therefore available to debuggers) and scoped (so can apply to specific blocks only).

However anything declared as const will still use memory, it is just a normal variable. The only difference is that it is constant and can't be changed after the initialisation that occurs during declaration. If the compiler is clever and the constant is globally scoped it can replace it with a literal.

This post on Stack Exchange has some more thorough technical information, and it suggests declaring it as both static and const.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top