It is preferable to declare immutable values using const
, rather than as macro definitions. Using a const
declared value means that the compiler is able to check the type of the object, the object has scope, and debugging tools will be able to show the name of the object. For integer constants, it is preferable to use an enum
as this guarantees that storage will not be required for the value.
Non-Compliant Code Example 1
In this example, PI
is defined using a macro. In the code, the value is introduced by textual subsitution.
#define PI 3.14159 ... float degrees; float radians; ... radians = degrees*PI/180;
Compliant Solution 1
In this compliant solution, the constant is defined as a const
variable.
float const pi = 3.14159; ... float degrees; float radians; ... radians = degrees*pi/180;
Non-Compliant Code Example 2
In this example, an integer value is defined using a macro.
#define MAX 42 ... for (int i = 0; i < max; ++i) { ... }
Compliant Solution 2
This compliant solution uses an enum
rather than a macro definition.
int const max = 42; ... for (int i = 0; i < MAX; ++i) { ... }
Exceptions
Values declared using const
cannot be used where compile-time constants are required. So, a const-qualified value cannot be used to specify the
- size of a bit-field member of a structure
- size of an array
- value of an enumeration constant
- value of a
case
constant.
If any of these are required, then an enum
or a macro definition must be used.
Risk Assessment
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
DCL00-A |
1 (low) |
1 (unlikely) |
2 (medium) |
P2 |
L3 |
References
- ISO/IEC 9899-1999 Sections 6.3.2.1, "Lvalues, arrays, and function designators"; 6.7.2.2, "Enumeration specifiers"; 6.10.3, "Macro replacement"