DSPRelated.com
Forums

OT: precision of compilers / preprocessors?

Started by Andre January 27, 2011
On Fri, 28 Jan 2011 09:15:28 +0100, David Brown
<david@westcontrol.removethisbit.com> wrote:

>#define FRAME_LEN 8192 >#define FM_SCALE (0x80000000ul / (FRAME_LEN / 2)) > >This will work on any compiler. > >Alternatively, use Vladmir's suggestion of using const: > >static const uint32_t FRAME_LEN = 8192; >static const uint32_t FM_SCALE = (0x100000000 / FRAME_LEN); > >If the compiler doesn't like it, it should give you an error. Your code >is neater and has stronger type-safety. However, this relies on the >compiler doing it's job well - some compiler's can't optimise code with >constants as well as they can with macros.
The problem with const is it generates a variable in RAM in C (but flags it in the compiler as read-only), which itself may not be a problem (unless RAM is really tight), but one consequence of that is you can't use it to dimension an array the way you can a macro-defined constant. C++ does this correctly so you CAN dimension an array with a value defined in a const, reducing the reliance on macros in C++. I suspect the C thing was a kludge in ANSI C or some other version of an earier C standard. Admittedly, the vast majority of these things ARE improvements, but const in C is as much a tease as a real improvement.
On 02/02/2011 06:51, Ben Bradley wrote:
> On Fri, 28 Jan 2011 09:15:28 +0100, David Brown > <david@westcontrol.removethisbit.com> wrote: > >> #define FRAME_LEN 8192 >> #define FM_SCALE (0x80000000ul / (FRAME_LEN / 2)) >> >> This will work on any compiler. >> >> Alternatively, use Vladmir's suggestion of using const: >> >> static const uint32_t FRAME_LEN = 8192; >> static const uint32_t FM_SCALE = (0x100000000 / FRAME_LEN); >> >> If the compiler doesn't like it, it should give you an error. Your code >> is neater and has stronger type-safety. However, this relies on the >> compiler doing it's job well - some compiler's can't optimise code with >> constants as well as they can with macros. > > The problem with const is it generates a variable in RAM in C (but > flags it in the compiler as read-only), which itself may not be a > problem (unless RAM is really tight), but one consequence of that is > you can't use it to dimension an array the way you can a macro-defined > constant. C++ does this correctly so you CAN dimension an array with a > value defined in a const, reducing the reliance on macros in C++. >
With a good compiler, "static const" will not generate data in ram - unless you do something silly like take its address, or use it in messy casts. Normally it will be optimised exactly as though it were a #define'd value, since the compiler knows it cannot change value. Note that without the "static", the const must have external linkage and must therefore exist in memory. The compiler will put it in read-only memory, but also limit code optimisation on the assumption that it might change value. This is why in C++, a plain "const" is a "static const", not an "extern const" as it is in C. It is correct that you can't use it as an array size (except for local arrays on the stack), which is a missing feature of C99. (It is valid in C++ - any compile-time constant can be used as an array size). It is also illegal to use a "static const" in a switch case. A sort of middle-ground between #define and "static const" is: enum { FRAME_LEN = 8192 }; Then it is a proper symbol, not a pre-processor symbol (and therefore has a type, and is visible to the debugger), and it can be used as an array size and a case label.
> I suspect the C thing was a kludge in ANSI C or some other version of > an earier C standard. Admittedly, the vast majority of these things > ARE improvements, but const in C is as much a tease as a real > improvement. >
const is good, but it doesn't go all the way - you are not allowed to modify a "const" object, and the results of the modification are undefined, and yet the compiler is not allowed to assume that "const" objects are actually constant. Still, it is not as weird as Pascal, where "const" is used to mean "variable with an initial value", or C++ where "const" for objects means "it looks constant from the outside" - the internal state of the object can easily be modified if it has mutable members.