CertC-EXP07

Do not diminish the benefits of constants by assuming their values in expressions

Required inputs: IR

If a constant value is given for an identifier, do not diminish the maintainability of the code in which it is used by assuming its value in expressions. Simply giving the constant a name is not enough to ensure modifiability; you must be careful to always use the name, and remember that the value can change. This recommendation is related to DCL06-C. Use meaningful symbolic constants to represent literal values.

Noncompliant Code Example

The header stdio.h defines the BUFSIZ macro, which expands to an integer constant expression that is the size of the buffer used by the setbuf() function. This noncompliant code example defeats the purpose of defining BUFSIZ as a constant by assuming its value in the following expression:

#include <stdio.h>
/* ... */
nblocks = 1 + ((nbytes - 1) >> 9); /* BUFSIZ = 512 = 2^9 */

The programmer's assumption underlying this code is that "everyone knows that BUFSIZ equals 512," and right-shifting 9 bits is the same (for positive numbers) as dividing by 512. However, if BUFSIZ changes to 1024 on some systems, modifications are difficult and error prone.

Compliant Solution

This compliant solution uses the identifier assigned to the constant value in the expression:

#include <stdio.h>
/* ... */
nblocks = 1 + (nbytes - 1) / BUFSIZ;

Most modern C compilers will optimize this code appropriately.

Risk Assessment

Assuming the value of an expression diminishes the maintainability of code and can produce unexpected behavior under any circumstances in which the constant changes.

Recommendation Severity Likelihood Remediation Cost Priority Level
EXP07-C Low Unlikely Medium P2 L3
Related Guidelines
SEI CERT C++ Coding Standard VOID EXP07-CPP. Do not diminish the benefits of constants by assuming their values in expressions
Bibliography
[ Plum 1985] Rule 1-5
Excerpt from SEI CERT C Coding Standard: Rules for Developing Safe, Reliable, and Secure Systems (2016 Edition) and SEI CERT C Coding Standard [https://cmu-sei.github.io/secure-coding-standards/sei-cert-c-coding-standard/recommendations/expressions-exp/exp07-c], Copyright (C) 1995-2026 Carnegie Mellon University. See section 9.4. "3rd-Party Licenses" in the documentation for full details.

Possible Messages

Key

Text

Severity

Disabled

magic_number

Use of magic literal.

None

False

magic_number_without_token

Use of magic literal.

None

False

possible_magic_number

Potential use of magic literal.

None

False

Options

allow_nonconst_variable_initialization

allow_nonconst_variable_initialization : bool = False

If set to true, allow magic numbers in the initialization of variables, even if the variable is not const. This option only applies to the initialization as part of the variable declaration, not to any later assignments.
 

allowed

allowed : set[float] = {0.0, 1.0, 2.0}

Literal values that are ok.
 

allowed_contexts

allowed_contexts : set[bauhaus.ir.PIR_Class_Name | typing.Callable[[bauhaus.ir.Node], bool]] = set()

Optional set of PIR classes or functions ((node) -> bool) for allowed contexts, e.g. Case_Label.
 

exceptions

exceptions : typing.Callable[[bauhaus.ir.Node], bool] | None = None

Optional predicate to filter out cases that should be allowed as an exception. The predicate takes a literal node and returns True if the given node is such an exception.
 

exclude_pp_literals

exclude_pp_literals : bool = True

If true, literals in conditions of #if are ignored.
 

exclude_single_uses

exclude_single_uses : bool = False

If true, report only literals used more than once.