This is the single biggest source of confusion I've noticed while maintaining C code,
and it's time consuming and error prone to retroactively fix string buffer issues.
So here are some simple rules for using these buffers and associated functions.
snprintf & strncpy
These functions should specify the full size of the destination buffer, because snprintf will NUL terminate, and with strncpy there is no way to determine if the string was truncated without checking the last character of the buffer. Using memset, to zero the buffer before using these functions is redundant and inefficient. Here is an example of correct usage:#include <stdio.h>
#include <string.h>
int main(void) {
char dest[5];
char src[5]="hello"; //Not NUL terminated
dest[sizeof(dest)-1]='\0'; //for later check
(void) strncpy(dest, src, sizeof(dest));
if (dest[sizeof(dest)-1]!='\0'); //truncated
dest[sizeof(dest)-1]='\0'; //should always do this
int required = snprintf(dest, sizeof(dest), "%s", src);
if (required >= sizeof(dest)); //truncated
}
Alternatives to consider if available are asnprintf,
strlcpy and strlcat
or to use variable length string buffers.
Note also that strcat is inefficient as it continually has to search for NUL, so instead
consider using stpcpyinstead of both strcpy and strcat.
static allocation
It's also worth noting how string buffers are allocated by the compiler. I.E. beware of sizeof on stringschar* string1="12345678"; char string2[]="12345678"; char string3[8]="12345678"; /* C99 supports excluding NUL C++ does not. */ #define string4 "12345678" //sizeof(string1) = 4 (sizeof pointer!) //sizeof(string2) = 9 (NUL char counted!) //sizeof(string3) = 8 (Not NUL terminated!) //sizeof(string4) = 9 (NUL char counted!)In the string declarations above note that string1 is readonly, even though it's not declared const. I.E. you will get a runtime error rather than a compile time one if you try to modify it. string2 and string3 are writable as the compiler will generate code to copy the string from a readonly data segment to the array at runtime.
© Sep 17 2008