Wiki Markup |
---|
This standard recommends the inclusion of diagnostic tests into your program using the {{assert()}} macro or other mechanisms (see \[[MSC11-A. Incorporate diagnostic tests using assertions]]). Static assertion is a new facility in the C++ )X0X draft standard. This facility gives the ability to make assertions at compile time rather than runtime, providing the following advantages: |
...
In a static assert declaration the constant-expression
is a constant expression that can be contextually converted to bool
. If the value of the expression when converted is true, the declaration has no effect. Otherwise the program is ill-formed, and a diagnostic message (which includes the text of the string-literal
is issued at compile time.
While not yet available in C, this behavior can be mimicked as follows:
For example:
Code Block |
---|
|
Code Block |
#define JOIN(x, y) JOIN_AGAIN(x, y) #define JOIN_AGAIN(x, y) x ## y #define compile_time_assert(e) \ typedef char JOIN(assert_, __LINE__) [(e) ? 1 : -1] int main(void) { static_assert(sizeof(int) <= sizeof(long), "sizeof(int) <= sizeof(long)"); /* Passes */ static_assert(sizeof(double) <= sizeof(int), "sizeof(double) <= sizeof(int)"); /* Fails */ } |
...
...
The {{JOIN()}} macro used the {{##}} operator \[[ISO/IEC 9899-1999|AA. C References#ISO/IEC 9899-1999]\] to concatenate tokens. See \[[PRE05-A. Understand macro replacement]] to understand how macro replacement behaves in C when using the {{##}} operator.
The macro argument string-literal
is ignored in this case, this is meant for future compatibility.
Non-Compliant Code Example
...
For assertions involving only constant expressions, some C++ compilers let you implementations allow the use a preprocessor conditional statement, as in:
Code Block | ||
---|---|---|
| ||
struct timer {
uint8_t MODE;
uint32_t DATA;
uint32_t COUNT;
};
#if (offsetof(timer, DATA) != 4)
#error DATA must be at offset 4
#endif
|
C99 does not recognize sizeof
, offsetof
and enumeration constants in #if
conditions (see C99, Section 6.10.1, "Conditional inclusion"). Some compilers allow these constructs in conditionals as an extension, but most do not.
Compliant Solution
This compliant solution ..mimics the behavior of static_assert
in a portable manner.
Code Block | ||
---|---|---|
| ||
#define JOIN(x, y) JOIN_AGAIN(x, y) static_assert(sizeof(long) >= 8, "64-bit code generation required for this library."); #define JOIN_AGAIN(x, y) x ## y #define static_assert(e, s) \ typedef char JOIN(assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1] struct timer { uint8_t MODE; uint32_t DATA; uint32_t COUNT; }; static_assert(offsetof(timer, DATA) == 4, "offsetof(timer, DATA) == 4"); |
The static_assert()
macro accepts a constant expression e
which is evaluated as the first operand to the conditional operator. If e
evaluates to 0, an array type with a dimension of 1 is defined; otherwise an array type with a dimension of -1 is defined. Because it is illegal to declare an array with a negative dimension, the resulting type definition will be flagged by the compiler. The name of the array is used to indicate the location of the failed assertion.
The macro argument string-literal
is ignored in this case, this is meant for future compatibility.
Wiki Markup |
---|
The {{JOIN()}} macro used the {{##}} operator \[[ISO/IEC 9899-1999|AA. C References#ISO/IEC 9899-1999]\] to concatenate tokens. See \[[PRE05-A. Understand macro replacement]] to understand how macro replacement behaves in C when using the {{##}} operator. |
Risk Assessment
Recommendation | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
DCL03-A | 1 (low) | 1 (unlikely) | 1 (high) | P1 | L3 |
...
Wiki Markup |
---|
\[[ISO/IEC 9899-1999|AA. C References#ISO/IEC 9899-1999]\] Section 6.10.1, "Conditional inclusion," and Section 6.10.3.3, "The ## operator" [Klarer 04] R. Klarer, J. Maddock, B. Dawes, and H. Hinnant. "Proposal to Add Static Assertions to the Core Language (Revision 3)" (ISO C++ committee paper ISO/IEC JTC1/SC22/WG21/N1720, October 2004). This document is available online at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1720.html. |
Wiki Markup |
---|
\[Saks 08] Dan Saks, Stephen C. Dewhurst. Presentation. Sooner Rather Than Later: Static Programming Techniques for C++.
\[Saks 05] Dan Saks. [_Catching errors early with compile-time assertions|http://www.embedded.com/columns/programmingpointers/164900888?_requestid=287187]. Embedded Systems Design. June, 2005.
\[Eckel 2007] Bruce Eckel. [_Thinking in C++ - Volume 2_|http://bruce-eckel.developpez.com/livres/cpp/ticpp/v2/]. January 25, 2007. |
...