...
In this noncompliant code example, the char
pointer p
is initialized to the address of a string literal. Attempting to modify the string literal results in undefined behavior.
Code Block | ||||
---|---|---|---|---|
| ||||
char *p = "string literal"; p[0] = 'S'; |
...
As an array initializer, a string literal specifies the initial values of characters in an array, as well as the size of the array. (See rule STR36-C. Do not specify the bound of a character array initialized with a string literal.) This code creates a copy of the string literal in the space allocated to the character array a
. The string stored in a
can be safely modified.
Code Block | ||||
---|---|---|---|---|
| ||||
char a[] = "string literal"; a[0] = 'S'; |
...
In this noncompliant code example, a string literal is passed to the (pointer to non-const
) parameter of the POSIX function mkstemp()
, which then modifies the characters of the string literal.
Code Block | ||||
---|---|---|---|---|
| ||||
char *fname; fname = mkstemp("/tmp/edXXXXXX"); |
...
Instead of passing a string literal, use a named array:
Code Block | ||||
---|---|---|---|---|
| ||||
static char fname[] = "/tmp/edXXXXXX"; mkstemp(fname); |
...
In this noncompliant example, the non-const char*
result of the strrchr()
function is used to modify the object pointed to by pathname
. Since the pointer points to a string literal, the effects of the modification are undefined and are likely to cause a signal, such as SIGSEGV
, to be generated for the process if the object is stored in read-only memory.
Code Block | ||||
---|---|---|---|---|
| ||||
const char* get_dirname(const char* pathname) { char* slash; slash = strrchr(pathname, '/'); if (slash) *slash = '\0'; /* undefined behavior */ return pathname; } int main() { puts(get_dirname(__FILE__)); return 0; } |
...
A compliant solution avoids modifying a const object, even if it is possible to obtain a non-const pointer to such an object by calling a standard C library function, such as strrchr()
. To reduce the risk of callers of get_dirname()
passing constant objects to the function, the argument is declared to be a non-const pointer. While converting a string literal to non-const char*
is permitted by the language, conforming compilers could issue a diagnostic for such code. See also recommendation EXP05-C. Do not cast away a const qualification.
Code Block | ||||
---|---|---|---|---|
| ||||
char* get_dirname(char* pathname) { char* slash; slash = strrchr(pathname, '/'); if (slash) *slash = '\0'; return pathname; } int main() { char pathname[] = __FILE__; /* calling get_dirname(__FILE__) may be diagnosed */ puts(get_dirname(pathname)); return 0; } |
...