Avoid the use of magic numbers in code when possible. Magic numbers are constant values that represent an arbitrary value such as a determined appropriate buffer size, or a malleable concept such as the age a person is considered an adult which could change between geopolitical boundaries. Rather, use appropriately named symbolic constants clarify the intent of the code. In addition, if a specific value needs to be changed reassigning a symbolic constant once is more efficient and less error prone then replacing every instance of the value to be changed.
Non Compliant Code Example
The meaning of the numeric literal 18 is not clear in this example.
Code Block | ||
---|---|---|
| ||
/* ... */ if (age >= 18) { /* Take action */ } else { /* Take a different action */ } /* ... */ |
Compliant Solution
The compliant solution replaces 18 with the symbolic constant ADULT_AGE
to clarify the meaning of the code.
Wiki Markup |
---|
When declaring immutable symbolic values, such as {{ADULT_AGE}} it is best to declare them as a constant in accordance with \[[DCL00-A. Declare immutable values using enum or const]\]. |
Code Block | ||
---|---|---|
| ||
enum { ADULT_AGE=18 }; /* ... */ if (age >= ADULT_AGE) { /* Take action */ } else { /* Take a different action */ } /* ... */ |
Exceptions
While replacing numeric constants with a symbolic constant is often a good practice, it can be taken too far. Exceptions can be made for constants that are themselves the abstraction you want to represent, as in this compliant solution.
Code Block | ||
---|---|---|
| ||
x = (-b + sqrt(b*b - 4*a*c)) / (2*a); |
Replacing numeric constants with symbolic constants in this example does nothing to improve the readability of the code, and may in fact make the code more difficult to read:
Code Block |
---|
enum { TWO = 2 }; /* a scalar */ enum { FOUR = 4 }; /* a scalar */ enum { SQUARE = 2 }; /* an exponent */ x = (-b + sqrt(pow(b, SQUARE) - FOUR*a*c))/ (TWO * a); |
When implementing recommendations it is always necessary to use sound judgment.
Risk Assessment
Using numeric literals makes code more difficult to read and understand. Buffer overruns are frequently a consequence of a magic number being changed in one place (like an array declaration) but not elsewhere (like a loop through an array).
Recommendation | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
DCL06-A | 1 (low) | 1 (unlikely) | 2 (medium) | P2 | L3 |
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
Wiki Markup |
---|
[http://www.doc.ic.ac.uk/lab/cplus/c++.rules/chap10.html] \[[ISO/IEC 9899-1999|AA. C References#ISO/IEC 9899-1999]\] Section 6.7, "Declarations" |
DCL05-A. Use typedefs to improve code readability 02. Declarations and Initialization (DCL) DCL07-A. Include the appropriate type information in function declarators