简体   繁体   中英

strcat vs strncat for string literal

I want to append a string literal to destination. I can use strcat or strncat :

strcat(dest, "values");

Or

strncat(dest, "values", sizeof("values") - 1);

strcat has shorter code, it looks neat.

But I wonder about their runtime performance.

Is strncat slightly faster at runtime because there's no need to locate terminator?

Or maybe compilers could do optimization and so there is no difference?

First, both strcat and strncat loks for the null terminator, the difference is that strncat also check for the size of the copied data, and will copy only n bytes.

Second, since strcat does not check for the size of the copied data, and copies until it gets to a null terminator, it might (and will!!) cause a buffer overflow, overriding data that is stored in memory after the buffer you copy to.

Third, your usage of the strncat is not safer, as you limit the copy by the size of the source buffer, not the destination buffer. Eg to use it correctly you should pass the size of the destination buffer:

strncat(dest, "values", sizeof(dest) -1 );

Fourth, if the size of the source string is bigger than than n of the destination, a null terminator will not be appended, so after the call to strncat you should add it yourself:

strncat(dest, "values", sizeof(dest) -1 );
dest[sizeof(dest) - 1] = '\0';

Last thing, since this is strncat, and it copies to wherever the destination string terminates, the size calculation is slightly more complex and is actually:

strncat(dest, "values", total_size_of_dest_buffer - strlen(dest) - 1 );
  1. I am absolutely sure, that performance is not an issue here.
  2. If you take a look at sources of both functions strcpy() and strncpy() (from glibc) you'll find out that both of them need to iterate over each character of src argument.
  3. Use strcpy() as it's much easier to read and maintain, and is less error-prone.

Also, if there is anything that could optimize this code, I guess any decent compiler will handle that, as it seems to be quite common expression.

Is strncat slightly faster at runtime because there's no need to locate terminator?

char *strncat(char * restrict s1, const char * restrict s2, size_t n);

Unlikely. In general, char *strncat() needs to locate a null character in s2 , if it exists before s2[n] , as concatenation stop before n characters. Of course, the null character in s2 of strcpy(s1,s2) needs to be found.

strncat(dest, "values", sizeof("values") - 1); may be slower than strcat(dest, "values"); and is not safer .

Code that does not overrun the array that may truncate:

// Assuming dest is an array
strncat(dest, "values", sizeof dest - strlen(dest) - 1);

An optimization compiler is allowed to "look-inside" well known functions like the ones below and emit code that "knows" the length/size of "values". such a compiler would certainly make equivalent performance code for the 2 below as the resultant functionality is identical - in this case.

strcat(dest, "values");
// or
strncat(dest, "values", sizeof("values") - 1);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM