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
}
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"; #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