DSPRelated.com
Forums

#define vs. const

Started by Kesh November 22, 2004
Hi,

Can anyone tell me if there is any advantage of using #define vs. const 
(or vice versa) in TI CCS (in C)?

E.g.

    #define myConst 1/256

vs.

    const float myConst = 1/256;

then use it like:

    b = a*myConst;

Thanks!
Kesh
Kesh wrote:

> Hi, > > Can anyone tell me if there is any advantage of using #define vs. const > (or vice versa) in TI CCS (in C)? > > E.g. > > #define myConst 1/256 > > vs. > > const float myConst = 1/256; > > then use it like: > > b = a*myConst; > > Thanks! > Kesh
#define myConst 1/256 will make a preprocessor define, which will appear in the code as a text substitution. You may have trouble because of the textual nature, so you should wrap the constant in parenthesis for consistent behavior: #define myConst (1/256). const float myConst = 1/256; will make allocate memory, evaluate 1/256 and stuff the result in there. In files where the definition is visible the compiler will, if it's faster, use the known value rather than the memory location. You have a bug in there, in that 1/256 will be evaluated as an integer operation with the value 0. When stuck into a floating point number the value will _still_ be 0. This could be worked around with your define, i.e. (float)myConst would have evaluated to 0.0039..., but (float)(myConst) would not, to the confusion of all. You are probably looking for static const myConst = 1.0 / 256.0; This corrects your integer evaluation problem, and it will also give CCS enough guidance that it will not allocate memory for myConst unless you take it's address, rather it will replace references to myConst with the correct floating point constant. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com
Tim,

Thanks for a quick reply!

> #define myConst 1/256 will make a preprocessor define, which will appear > in the code as a text substitution. You may have trouble because of the > textual nature, so you should wrap the constant in parenthesis for > consistent behavior: > > #define myConst (1/256). > > const float myConst = 1/256; will make allocate memory, evaluate 1/256 > and stuff the result in there. In files where the definition is visible > the compiler will, if it's faster, use the known value rather than the > memory location.
So let me see if I understood the whole thing correctly. while #define is like a macro and it just replaces myConst with (1.0/256.0) while const... precomputes 1.0/256.0 and stores it to a memory location. Have I understood this correctly? I presume that when you go the #define route, the compiled DSP code still computes 1.0/256.0 in the program. If this is true, then the most optimal code is: #define myConst 0.00390625 // = (1.0/256.0) ... b = a*myConst; ... Am I right? Thanks!! Kesh
Kesh wrote:

-snip-
> > So let me see if I understood the whole thing correctly. while #define > is like a macro and it just replaces myConst with (1.0/256.0) while > const... precomputes 1.0/256.0 and stores it to a memory location. Have > I understood this correctly?
Yes, except that adding the "static" to the "const ..." will make it act exactly like a define with Code Composter. In fact the #define construct _is_ a preprocessor macro, and is often referred to as such. My favorite reference on this is Harbison & Steele, "C: A Reference Manual". It goes into great depth on this sort of thing (including all the pitfalls).
> > I presume that when you go the #define route, the compiled DSP code > still computes 1.0/256.0 in the program. If this is true, then the most > optimal code is: > > #define myConst 0.00390625 // = (1.0/256.0) > > ... > > b = a*myConst; > > ... > > Am I right? > > Thanks!! > Kesh
In theory different compilers will do this differently, and in the past this has been true (up to and including compilers that barf when presented with the necessity of doing a floating point calculation in the preprocessor). These days it's a rare compiler that won't take the (1.0 / 256.0) and calculate the constant, and Code Composter does it perfectly. This means that you can choose the define in a way that illuminates it's meaning, rather than trying to give the compiler hints that will reduce the readability of your code. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com
Tim,

Thanks for valuable tips. The Harbison-Steele book has been ordered :)

I guess the bottom line is that there isn't whole lot of difference 
between the two (as long as I define it with "static const"). I will 
play around with CCS later and see if I can trace it myself. The only 
problem is that I've been an ADI person up until this project and not 
familiar with TI assembly... Oh well, gotta start somewhere.

Kesh

Tim Wescott wrote:
> Kesh wrote: > > -snip- > >> >> So let me see if I understood the whole thing correctly. while #define >> is like a macro and it just replaces myConst with (1.0/256.0) while >> const... precomputes 1.0/256.0 and stores it to a memory location. >> Have I understood this correctly? > > > Yes, except that adding the "static" to the "const ..." will make it act > exactly like a define with Code Composter. In fact the #define > construct _is_ a preprocessor macro, and is often referred to as such. > My favorite reference on this is Harbison & Steele, "C: A Reference > Manual". It goes into great depth on this sort of thing (including all > the pitfalls). > >> >> I presume that when you go the #define route, the compiled DSP code >> still computes 1.0/256.0 in the program. If this is true, then the >> most optimal code is: >> >> #define myConst 0.00390625 // = (1.0/256.0) >> >> ... >> >> b = a*myConst; >> >> ... >> >> Am I right? >> >> Thanks!! >> Kesh > > > In theory different compilers will do this differently, and in the past > this has been true (up to and including compilers that barf when > presented with the necessity of doing a floating point calculation in > the preprocessor). These days it's a rare compiler that won't take the > (1.0 / 256.0) and calculate the constant, and Code Composter does it > perfectly. This means that you can choose the define in a way that > illuminates it's meaning, rather than trying to give the compiler hints > that will reduce the readability of your code. >
Kesh wrote:

> Tim, > > Thanks for valuable tips. The Harbison-Steele book has been ordered :) > > I guess the bottom line is that there isn't whole lot of difference > between the two (as long as I define it with "static const"). I will > play around with CCS later and see if I can trace it myself. The only > problem is that I've been an ADI person up until this project and not > familiar with TI assembly... Oh well, gotta start somewhere. > > Kesh >
The functional difference is that the #define construct just goes in as a textual substitution, so you can have something really screwy like #define start1(x) (x) = 23 + #define end1(y) (42 * y) If you then refer to them as start1(myLvalue) end1(ralph); it'll compile and run -- but you'll never, ever be able to debug. The "static const" construct, on the other hand, does all the typechecking that the compiler does, so if you do something that's out of line you'll get a warning or an error. I once worked at a company who's software department was recovering from a programmer who seemed to think of C as an assembler to go along with the C preprocessor -- she went as far as having multiple open braces in some macros that were matched by the same number in other macros. It was certainly very intriguing, but it didn't lend itself to maintenance. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com

Tim Wescott wrote:

(snip)

> I once worked at a company who's software department was recovering from > a programmer who seemed to think of C as an assembler to go along with > the C preprocessor -- she went as far as having multiple open braces in > some macros that were matched by the same number in other macros. It > was certainly very intriguing, but it didn't lend itself to maintenance.
I have heard stories of ex-Pascal programmers doing: #define BEGIN { #define END } and maybe worse. -- glen
On Mon, 22 Nov 2004 13:58:56 -0800, Tim Wescott wrote:

> Kesh wrote: > > -snip- >> >> So let me see if I understood the whole thing correctly. while #define >> is like a macro and it just replaces myConst with (1.0/256.0) while >> const... precomputes 1.0/256.0 and stores it to a memory location. Have >> I understood this correctly?
Pretty much. The difference (semantically) is that the const has an address which can be taken with the &() operator and the #define doesn't, and so it can't. Similarly, you can test the value of the #define with other pre-processor constructs (#if, #ifdef), and you can't do that for the const.
> Yes, except that adding the "static" to the "const ..." will make it act > exactly like a define with Code Composter. In fact the #define > construct _is_ a preprocessor macro, and is often referred to as such. > My favorite reference on this is Harbison & Steele, "C: A Reference > Manual". It goes into great depth on this sort of thing (including all > the pitfalls). >> >> I presume that when you go the #define route, the compiled DSP code >> still computes 1.0/256.0 in the program. If this is true, then the most >> optimal code is: >> >> #define myConst 0.00390625 // = (1.0/256.0) >> >> ... >> >> b = a*myConst; >> >> ... >> >> Am I right? >> >> Thanks!! >> Kesh > > In theory different compilers will do this differently, and in the past > this has been true (up to and including compilers that barf when > presented with the necessity of doing a floating point calculation in > the preprocessor). These days it's a rare compiler that won't take the > (1.0 / 256.0) and calculate the constant, and Code Composter does it > perfectly. This means that you can choose the define in a way that > illuminates it's meaning, rather than trying to give the compiler hints > that will reduce the readability of your code.
It's not (in general) the preprocessor that's computing the constant, but the C compiler, which gets to see the expression of constants and says: I can do constant folding here. Compilers are supposed to be able to do constant folding with expressions that contain const "variables" (if the const is in scope at the time), but I've seen far fewer of those that work. That's why I mainly stick with #defines for my constants. I like my constant expressions resolved at compile time. -- Andrew
"Kesh" <tikuma@hotmail.com> wrote in message
news:cntf2e$2o1$1@solaris.cc.vt.edu...
> Hi, > > Can anyone tell me if there is any advantage of using #define vs. const > (or vice versa) in TI CCS (in C)?
I have never used CCS, but there are some good articles on the web (Embedded.com?) on this topic. The advantage as Tim already pointed out is the memory allocation associated with const vs no allocation in #define(although I'm not sure I understood his static construct and why it is equivalent to the define) The const declaration provides much better type checking in your code. It also makes the variable available in your debugger (by name). If it is only a few definitions, I think the const is a better practice (since the memory penalty is not going to be significant). If it is, then your system has no margin and requires a review. Cheers Bhaskar
> > E.g. > > #define myConst 1/256 > > vs. > > const float myConst = 1/256; > > then use it like: > > b = a*myConst; > > Thanks! > Kesh
Andrew Reilly wrote:

-snip-
> Compilers are supposed to be able to do constant folding with expressions > that contain const "variables" (if the const is in scope at the time), but > I've seen far fewer of those that work. That's why I mainly stick with > #defines for my constants. I like my constant expressions resolved at > compile time. >
The compiler for the 320F28xx that comes with Code Composter puts an entirely new spin on the phrase "aggressive optimization". In many ways that's a pain in the a** because they can diverge from ANSI, but in this case it's nice because you get nicely typechecked constants. But I think you're right in general, at least at the moment, that if you want your constants to be resolved as constants at compile time you need to force it with #define. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com