Prefer type definitions (typedef
) to macro definitions (#define
) when encoding types. Type definitions obey scope rules where defines do not. Type definitions can also correctly encode pointer types because they are not implemented as simple textual substitution. For example, in the following example:
typedef char *NTCS; const NTCS p = &data;
The variable p
is declared as a constant pointer to char
[[Summit 05]]. This can be confusing to developers who think that type definitions are implemented using textual substitution. As a result, Dan Saks recommends placing type qualifiers as the rightmost declaration specifier when qualifying types without explicit pointer decorations [[Saks 99]]. While less confusing to some, this practice is not recommended because it is inconsistent with widely accepted practice and potentially misleading to experienced programmers.
Non-Compliant Code Example
In this non-compliant code example, s1
is declared as char *
, but s2
is declared as a char
, which is probably not the intention of the programmer.
#define string char * string s1, s2;
Compliant Solution
In this compliant solution, both s1
and s2
are declared as char *
.
typedef char * string; string s1, s2;
Risk Analysis
Recommendation |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
PRE03-A |
1 (low) |
1 (unlikely) |
3 (low) |
P3 |
L3 |
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[[ISO/IEC 9899-1999]] Section 6.7, "Declarations"
[[Saks 99]]
[[Summit 05]] Question 1.13, Question 11.11
PRE02-A. Macro replacement lists should be parenthesized 01. Preprocessor (PRE) DCL03 CS 1 typedef