【问题标题】:strcat vs strncat for string literalstrcat vs strncat 用于字符串文字
【发布时间】:2014-06-28 09:54:13
【问题描述】:

我想将字符串文字附加到目的地。我可以使用strcatstrncat

strcat(dest, "values");

或者

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

strcat 的代码更短,看起来很整洁。

但我想知道它们的运行时性能。

strncat 在运行时是否会稍微快一些,因为不需要定位终止符?

或者也许编译器可以进行优化,所以没有区别?

【问题讨论】:

  • 无论哪种方式,都需要找到dest 的空终止符。无论哪种方式,代码都需要遍历"values" 中的所有字符。所以没有区别。
  • @OliCharlesworth 我认为strncat 会读取到字节s,而strcat 会再读取一个字节,即空终止符。我一开始就错了?
  • @OliCharlesworth - strncat 将使程序员能够防止缓冲区溢出。 strcat没有这种奢侈
  • @EdHeal:确实。我只是在假设一个比另一个更快的前提下发表评论。

标签: c string compiler-construction concatenation


【解决方案1】:

首先,strcatstrncat 都用于空终止符,不同之处在于strncat 也会检查复制数据的大小,并且只会复制n 字节。

其次,由于strcat 不检查复制数据的大小,并且一直复制到空终止符,它可能(并且将会!!)导致缓冲区溢出,覆盖存储在内存中的数据在您复制到的缓冲区之后。

第三,您对 strncat 的使用并不安全,因为您通过源缓冲区的大小来限制副本,而不是目标缓冲区。例如。要正确使用它,您应该传递目标缓冲区的大小:

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

第四,如果源字符串的大小大于目标的n,则不会附加空终止符,所以在调用strncat之后你应该自己添加:

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

最后一件事,因为这是 strncat,它复制到目标字符串终止的地方,大小计算稍微复杂一些,实际上是:

strncat(dest, "values", total_size_of_dest_buffer - strlen(dest) - 1 );

【讨论】:

  • 1) strncat(dest, "values", sizeof(dest) -1 ); 不正确。可以使用strncat(dest, "values", sizeof(dest) - strlen(dest) - 1); 2)“如果源字符串的大小大于目标的n,则不会附加空终止符,”以及下面的strncat() 也是不对的。 strncat() 总是空字符终止。
【解决方案2】:
  1. 我非常肯定,性能在这里不是问题。
  2. 如果您查看 strcpy()strncpy()(来自 glibc)这两个函数的来源,您会发现它们都需要遍历 src 参数的每个字符。
  3. 使用strcpy(),因为它更易于阅读和维护,并且不易出错。

另外,如果有任何东西可以优化这段代码,我想任何体面的编译器都会处理它,因为它似乎是很常见的表达方式。

【讨论】:

  • 阅读源代码确实是正确的。我应该这样做的。谢谢你。尽管您的函数名称有拼写错误。
  • Ops...我已经修正了这些错别字。 ;)
  • 如果用法如 OP 所示,即将 strlen 作为第二个参数,那么 strcat 确实不易出错。但是使用 strncpy 的正确方法是将剩余的缓冲区空间作为第二个参数,如其他答案所示。
【解决方案3】:

strncat 在运行时是否会稍微快一些,因为不需要定位终止符?

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

不太可能。一般来说,char *strncat() 需要在s2 中定位一个空字符,如果它存在于s2[n] 之前,则作为n 字符之前的连接停止。当然, 空字符需要在strcpy(s1,s2)s2中找到。

strncat(dest, "values", sizeof("values") - 1); 可能strcat(dest, "values"); 并且不更安全

不会超出可能截断数组的代码:

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

允许优化编译器“查看”下面这些众所周知的函数,并发出“知道”“值”长度/大小的代码。这样的编译器肯定会为下面的 2 生成等效的性能代码,因为结果功能是相同的 - 在这种情况下。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-18
    • 2012-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-09
    • 2010-09-15
    • 2017-01-24
    相关资源
    最近更新 更多