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
strncpy
reaches the end ofsrc
before it copiescount
characters, 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
strncpy
copiescount
characters 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
'scount
argument doesn't include the terminating null character. This makes memory allocation a bit awkward since the character array must be allocated with at leastcount + 1
bytes in order to storecount
characters 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 withstrncpy
if you know thatstrlen(src) == count + 1
.
Compare all of this to snprintf
:
snprintf
copies at mostcount - 1
characters and a null character, meaning you need an array ofcount
elements to store it all. Sweet!- If
snprintf
reaches the end ofsrc
before it copiescount - 1
characters, it just adds a terminating null character todest
and halts - no questions asked. - If
snprintf
copiescount - 1
characters before it reaches the end ofsrc
, it still adds a terminating null character to the end ofdest
.
Why on earth is strncpy
this way?