...
This compliant solution avoids using leading or trailing underscores in the name of the header guard.:
Code Block | ||||
---|---|---|---|---|
| ||||
#ifndef MY_HEADER_H #define MY_HEADER_H /* contents of <my_header.h> */ #endif /* MY_HEADER_H */ |
...
In this noncompliant code example, the names of the file scope objects _max_limit
and _limit
both begin with an underscore. Since it is static
, the declaration of _max_limit
might seem to be impervious to clashes with names defined by the implementation. However, because the header <stddef.h>
is included to define size_t
, a potential for a name clash exists. (Note, however, that a conforming compiler may implicitly declare reserved names regardless of whether or not any C standard library header has been explicitly included.) In addition, because _limit
has external linkage, it may clash with a symbol with the same name defined in the language runtime library even if such a symbol is not declared in any header. Consequently, it is unsafe to start the name of any file scope identifier with an underscore even if its linkage limits its visibility to a single translation unit. Common effects of such clashes range from compiler errors to linker errors to abnormal program behavior at runtime.
...
In this compliant solution, names of no-file-scope objects begin with an underscore and hence do not encroach on the reserved name space.:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stddef.h> /* for size_t */ static const size_t max_limit = 1024; size_t limit = 100; unsigned int getValue(unsigned int count) { return count < limit ? count : limit; } |
...
This compliant solution avoids redefining reserved names or using reserved prefixes and suffixes.:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <inttypes.h> /* for int_fast16_t and PRIdFAST16 */ static const int_fast16_t MY_INTFAST16_UPPER_LIMIT = 12000; void print_fast16(int_fast16_t val) { enum { BUFSIZE = 80 }; char buf [BUFSIZE]; if (MY_INTFAST16_UPPER_LIMIT < val) sprintf(buf, "The value is too large"); else snprintf(buf, BUFSIZE, "The value is %" PRIdFAST16, val); /* ... */ } |
...
In addition to symbols defined as functions in each C standard library header, identifiers with external linkage include, among many others, errno
, math_errhandling
, setjmp()
, and va_end()
, regardless of whether or not any any of them is masked by a macro of the same name.
This noncompliant example provides definitions for the C standard library functions malloc()
and free()
. Although this practice is permitted by many traditional implementations of UNIX (e.g., the Dmalloc library), it is disallowed by the C Standard because it is not generally portable and may lead to undefined behavior. Common effects range from compiler errors to linker errors to abnormal program behavior at runtime. Even on systems where that allow replacing malloc()
is allowed, doing so without also replacing calloc()
and realloc()
is likely to cause problems as well.
...
The compliant, portable solution avoids redefining any C standard library identifiers with external linkage. In addition, it provides definitions for all memory allocation functions.:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stddef.h> void* my_malloc(size_t nbytes) { void *ptr; /* allocate storage from own pool and set ptr */ return ptr; } void* my_calloc(size_t nelems, size_t elsize) { void *ptr; /* allocate storage from own pool and set ptr */ return ptr; } void* my_realloc(void *ptr, size_t nbytes) { /* reallocate storage from own pool and set ptr */ return ptr; } void my_free(void *ptr) { /* return storage to own pool */ } |
...
Legacy code is apt to include an incorrect declaration, such as the following.:
Code Block | ||||
---|---|---|---|---|
| ||||
extern int errno; |
...
The correct way to declare errno
is to include the header <errno.h>
.:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <errno.h> |
...
In this noncompliant example, the identifiers for the C Standard Library standard library functions malloc()
and free()
are reserved.:
Code Block | ||||
---|---|---|---|---|
| ||||
void *malloc(size_t nbytes) { /* violation */ void *ptr; /* ... */ /* allocate storage from own pool and set ptr */ return ptr; } void free(void *ptr) { /* violation */ /* ... */ /* return storage to own pool */ } |
...
This complaint example changes the names of the identfiers to malloc_custom()
and free_custom()
.:
Code Block | ||||
---|---|---|---|---|
| ||||
void *malloc_custom(size_t nbytes) { void *ptr; /* ... */ /* allocate storage from own pool and set ptr */ return ptr; } void free_custom(void *ptr) { /* ... */ /* return storage to own pool */ } |
Exceptions
DCL37-EX0EX1: It is permissible to use reserved words in declarations when the risk of clashing with a preexisting variable is greater than the risk of clashing with a reserved word. In particular, the scope must be used in a macro that may be invoked with arbitrary preexisting variables (possibly as arguments). The The following code demonstrates a SWAP_UNSAFE()
macro that exchanges two values, and uses a __tmp
variable as a temporary value. This code is permitted because the temporary variable is more likely to clash with a non-reserved variable in the current scope than with a reserved word. This This code should be considered non-portablenonportable; as it requires the current platform to allow the use of __tmp
.
...
Such macros should only be used with great care. See rules PRE31-C. Avoid side - effects in arguments to unsafe macros and PRE00-C. Prefer inline or static functions to function-like macros for more information.
...
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
Compass/ROSE |
|
|
| ||||||
ECLAIR |
| resvidnt_resvmacr | Fully implemented. | ||||||
|
|
|
...