简体   繁体   English

strcat vs strncat用于字符串文字

[英]strcat vs strncat for string literal

I want to append a string literal to destination. 我想将字符串文字附加到目标。 I can use strcat or strncat : 我可以使用strcatstrncat

strcat(dest, "values");

Or 要么

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

strcat has shorter code, it looks neat. strcat代码较短,看起来很整洁。

But I wonder about their runtime performance. 但是我想知道它们的运行时性能。

Is strncat slightly faster at runtime because there's no need to locate terminator? 因为不需要定位终止符, strncat在运行时是否会稍微快一些?

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. 首先, strcatstrncat查找空终止符,不同之处在于strncat还检查复制数据的大小,并且仅复制n个字节。

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. 其次,由于strcat不会检查复制数据的大小,而是一直复制到空终止符,因此可能(并且将!!)导致缓冲区溢出,从而覆盖复制缓冲区之后存储在内存中的数据至。

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. 第三,对strncat的使用并不安全,因为您将复制限制为源缓冲区而不是目标缓冲区的大小。 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: 第四,如果源字符串的大小大于目标的n ,则不会附加空终止符,因此在对strncat的调用之后,您应该自己添加它:

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,并且它将复制到目标字符串终止的任何地方,所以大小计算稍微复杂一些,实际上是:

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. 如果查看一下strcpy()strncpy()这两个函数的源代码(来自glibc),您会发现它们都需要遍历src参数的每个字符。
  3. Use strcpy() as it's much easier to read and maintain, and is less error-prone. 使用strcpy()可以更轻松地读取和维护它,并且不易出错。

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? 因为不需要定位终止符, strncat在运行时是否会稍微快一些?

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. 通常,如果char *strncat()s2[n]之前存在,则需要在s2定位一个空字符 ,因为串联终止在n字符之前。 Of course, the null character in s2 of strcpy(s1,s2) needs to be found. 当然,需要找到strcpy(s1,s2) s2中的空字符

strncat(dest, "values", sizeof("values") - 1); may be slower than strcat(dest, "values"); 可能比strcat(dest, "values"); 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. 这样的编译器肯定会为下面的2做等效的性能代码,因为最终的功能是相同的-在这种情况下。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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