I just realized that I am in the habit of using snprintf for taking slices of strings, which now seems unconventional to me for several reasons (chiefly, the need to #include <stdio.h>). But after looking at strncpy more closely, I'm struggling to see why anyone would prefer it over snprintf.
To be clear, I'm comparing strncpy(dest, src, count) with snprintf(dest, count + 1, "%s", src). snprintf(dest, count + 1, src) obviously causes problems whenever src contains '%'.
What stood out to me most was how much more snprintf acts like an str- function than strncpy, which by comparison feels more like a mem- function to me.
- If
strncpyreaches the end ofsrcbefore it copiescountcharacters, it will writecount - strlen(src)null characters in addition to the terminating null character copied fromsrc.- This practice seems unnecessarily wasteful: functions expecting null-terminated strings (virtually every string function in C, for better or worse) would encounter the terminating null character and halt. Only
mem- functions would even notice the additional characters, but I can't imagine the difference would ever be particularly useful. Also, if you're actually dealing with byte arrays, why are you using string functions? - From what I can tell, this is by-and-large not how C tends to deal with either arrays or strings. For example,
char foo[6] = "hi";doesn't fill the remaining 3 bytes with null characters! Furthermore, in my experience, arrays are typically pre-initialized in this manner using... you guessed it,memset. Amem- function.
- This practice seems unnecessarily wasteful: functions expecting null-terminated strings (virtually every string function in C, for better or worse) would encounter the terminating null character and halt. Only
- If
strncpycopiescountcharacters before it reaches the end ofsrc, the resulting character array won't be null-terminated. That's right, the string copying function sometimes doesn't produce a valid string. What? strncpy'scountargument doesn't include the terminating null character. This makes memory allocation a bit awkward since the character array must be allocated with at leastcount + 1bytes in order to storecountcharacters as a proper null-terminated string. Even worse, the last character in the array still needs to be set to the null character, which you can only do withstrncpyif you know thatstrlen(src) == count + 1.
Compare all of this to snprintf:
snprintfcopies at mostcount - 1characters and a null character, meaning you need an array ofcountelements to store it all. Sweet!- If
snprintfreaches the end ofsrcbefore it copiescount - 1characters, it just adds a terminating null character todestand halts - no questions asked. - If
snprintfcopiescount - 1characters before it reaches the end ofsrc, it still adds a terminating null character to the end ofdest.
Why on earth is strncpy this way?