I am currently using static const in my code instead of using 'magic numbers'as mentioned in "static const" vs "#define" vs "enum".
void checkInvalidResponse (uint8_t response)
{
static const uint8_t INVALID_RESP = 0xFF;
if (response == INVALID_RESP)
{
/* Code for invalid response */
}
}
I, however, think that using static const would consume memory in the compiled code for INVALID_RESP. The statement would also translate to machine code that does a LOAD from the memory followed by the compare, instead of comparing with a value provided as part of the instruction. Is this correct? If so, then this solution would not be optimal in terms of speed and memory right?
I am currently changing the code to use #defines
void checkInvalidResponse (uint8_t response)
{
#define INVALID_RESP 0xFF
if (response == INVALID_RESP)
{
/* Code for invalid response */
}
}
However, since #define does not have a scope, would the behavior of the cut-and-paste aspect of #define be consistent across multiple compilers? For example, if INVALID_RESP is re-defined later, would any code in lines following the redefinition use the new value?
Another approach I have looked at is to use enumerations.
void checkInvalidResponse (uint8_t response)
{
typedef enum
{
INVALID_RESP = 0xFF
} resp_t;
if ((resp_t)response == INVALID_RESP)
{
/* Code for invalid response */
}
}
However, the typecasting to an enum would allocate more memory than needed (The processor would do a 32 bit(?) compare instead of an 8 bit compare).
What is the best method to use instead of using magic numbers in code?
I think in all cases, the compiler, at least with -O2 turned on, will generate the same code. It has gotten pretty hard to trick compilers into doing stupid things.
Typically, magic numbers are defined in a common header and used as needed throughout the code.
The bigger question for you is, does it matter? Is this something that is in the critical path of your code, and something you are going to be doing a very high percentage of the time? Given the name, I'd guess not.
Moving the definition to a header file will make your code less distracting. In checkInvalidResponse
, the reader couldn't care less exactly what is represented by INVALID_RESPONSE
, only that the test passes or fails.
In C language const
entities are not constants at language level, which significantly limits the usability of const
for defining manifest constants. Note that this is not about the efficiency of the generated code, it's about the basic validity ("compilability") of the code: in C language const
entities are simply not allowed in contexts that require constants.
For this reason in C language the only truly universal and versatile approach to defining manifest constants is C preprocessor (i.e. #define
), with enum
being another vialble alternative, but only where it is applicable (a significant drawback of enum
constants in C is the fact that they unconditionally have signed int
type).
Just use #define
and don't attempt to "scope" the constants. There's rearely any point in doing so. But if for some reason you need to restrict the scope of #define
'd constant, you can always use #undef
for that purpose.
enum
is guaranteed by the standard to support up to unsigned int
width.
If you use #define
there is no implicit specification of the width because the pre-compiler will just replace the symbol with the number (or whatever else was defined), so you can append L to the end of your number and guarantee long
values.
Frankly, I never had use for enums larger than integers myself...
http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf
6.7.2.2 Enumeration specifiers
[...]
Constraints
The expression that defines the value of an enumeration constant shall be an integer constant expression that has a value representable as an int.
[...]
Each enumerated type shall be compatible with char, a signed integer type, or an unsigned integer type. The choice of type is implementation-defined, but shall be capable of representing the values of all the members of the enumeration.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With