C语言 strcat Vs strncat - 什么时候应该使用哪个函数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6491038/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 09:00:28  来源:igfitidea点击:

strcat Vs strncat - When should which function be used?

cstring

提问by Jay

Some static code analyzer tools are suggesting that all strcat usage should be replaced with strncat for safety purpose?

一些静态代码分析器工具建议为了安全起见,所有 strcat 用法都应替换为 strncat ?

In a program, if we know clearly the size of the target buffer and source buffers, is it still recommended to go for strncat?

在一个程序中,如果我们清楚地知道目标缓冲区和源缓冲区的大小,是否仍然建议使用strncat?

Also, given the suggestions by static tools, should strcat be used ever?

另外,鉴于静态工具的建议,应该使用 strcat 吗?

回答by Pankaj Kumar

Concatenate two strings into a single string.

将两个字符串连接成一个字符串。

Prototypes

原型

#include <string.h>

char * strcat(char *restrict s1, const char *restrict s2);

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

DESCRIPTION

描述

The strcat()and strncat()functions append a copy of the null-terminated string s2 to the end of the null-terminated string s1, then add a terminating \0'. The string s1 must have sufficient space to hold the result.

strcat()strncat()功能追加空终止字符串S2的拷贝到空终止字符串S1的结尾,然后添加终止\ 0' 。字符串 s1 必须有足够的空间来保存结果。

The strncat() function appends not more than n characters from s2, and then adds a terminating \0'.

strncat() 函数从 s2 中添加不超过 n 个字符,然后添加一个终止的 \0'。

The source and destination strings should not overlap, as the behavior is undefined.

源字符串和目标字符串不应重叠,因为行为未定义。

RETURN VALUES

返回值

 The `strcat()` and `strncat()` functions return the pointer s1.

SECURITY CONSIDERATIONS

安全考虑

The strcat()function is easily misused in a manner which enables malicious users to arbitrarily change a running program's functionality through a buffer overflow attack.

strcat()函数很容易被滥用,使恶意用户能够通过缓冲区溢出攻击任意更改正在运行的程序的功能。

Avoid using strcat(). Instead, use strncat()or strlcat()and ensure that no more characters are copied to the destination buffer than it can hold.

避免使用strcat(). 相反,使用strncat()strlcat()并确保复制到目标缓冲区的字符不会超过它可以容纳的数量。

Note that strncat()can also be problematic. It may be a security concern for a string to be truncated at all. Since the truncated string will not be as long as the original, it may refer to a completely different resource and usage of the truncated resource could result in very incorrect behavior. Example:

请注意,这strncat()也可能有问题。字符串被截断可能是一个安全问题。由于截断的字符串不会像原始字符串一样长,因此它可能指代完全不同的资源,并且截断资源的使用可能会导致非常不正确的行为。例子:

void
 foo(const char *arbitrary_string)
 {
         char onstack[8] = "";

 #if defined(BAD)
         /*
          * This first strcat is bad behavior.  Do not use strcat!
          */
         (void)strcat(onstack, arbitrary_string);        /* BAD! */
 #elif defined(BETTER)
         /*
          * The following two lines demonstrate better use of
          * strncat().
          */
         (void)strncat(onstack, arbitrary_string,
             sizeof(onstack) - strlen(onstack) - 1);
 #elif defined(BEST)
         /*
          * These lines are even more robust due to testing for
          * truncation.
          */
         if (strlen(arbitrary_string) + 1 >
             sizeof(onstack) - strlen(onstack))
                 err(1, "onstack would be truncated");
         (void)strncat(onstack, arbitrary_string,
             sizeof(onstack) - strlen(onstack) - 1);
 #endif
 }

Example

例子

char dest[20] = "Hello";
char *src = ", World!";
char numbers[] = "12345678";

printf("dest before strcat: \"%s\"\n", dest); // "Hello"

strcat(dest, src);
printf("dest after strcat:  \"%s\"\n", dest); // "Hello, World!"

strncat(dest, numbers, 3); // strcat first 3 chars of numbers
printf("dest after strncat: \"%s\"\n", dest); // "Hello, World!123"

回答by Juho

If you are absolutely sure about source buffer's size and that the source buffer contains a NULL-character terminating the string, then you can safely use strcat when the destination buffer is large enough.

如果您绝对确定源缓冲区的大小并且源缓冲区包含终止字符串的 NULL 字符,那么当目标缓冲区足够大时,您可以安全地使用 strcat。

I still recommend using strncat and give it the size of the destination buffer - length of the destination string - 1

我仍然建议使用 strncat 并为其指定目标缓冲区大小 - 目标字符串的长度 - 1

Note: I edited this since comments noted that my previous answer was horribly wrong.

注意:我对此进行了编辑,因为评论指出我之前的答案非常错误。

回答by Jens Gustedt

They don't do the same thing so they can't be substituted for one another. Both have different data models.

他们不做同样的事情,所以他们不能互相替代。两者都有不同的数据模型。

  • A string for strcatis a null terminated string for which you (as the programmer) guarantee that it has enough space.
  • A string for strncatis a sequence of charthat is either terminated at the length you are indicating orby a null termination if it is supposed to be shorter than that length.
  • 字符串 forstrcat是一个空终止字符串,您(作为程序员)保证它有足够的空间。
  • 一种用于字符串strncat是一个序列char,其在要表示的长度不是终止以空终止,如果它被认为是比长度短。

So the use of these functions just depends on the assumptions that you may (or want to) do about your data.

因此,这些函数的使用仅取决于您可能(或想要)对数据做的假设。

回答by Lundin

Static tools are generally poor at understanding the circumstances around the use of a function. I bet most of them just warn for every strcat encountered instead of actually looking whether the data passed to the function is deterministic or not. As already mentioned, if you have control over your input data neither function is unsafe.

静态工具通常无法理解函数使用的环境。我敢打赌,他们中的大多数只是针对遇到的每个 strcat 发出警告,而不是实际查看传递给函数的数据是否是确定性的。如前所述,如果您可以控制输入数据,那么这两个函数都不是不安全的。

Though note that strncat() is slightly slower, as it has to check against '\0' termination and a counter, and also explicitly add it to the end. strcat() on the other hand just checks for '\0', and it adds the trailing '\0' to the new string by copying the terminator from the second string along with all the data.

尽管请注意 strncat() 稍微慢一些,因为它必须检查 '\0' 终止和计数器,并且还明确地将其添加到末尾。另一方面,strcat() 只检查 '\0',它通过复制第二个字符串中的终止符和所有数据,将尾随的 '\0' 添加到新字符串中。

回答by Kosar

It's very simple strcat is used to concatenate two strings , for example

很简单 strcat 用于连接两个字符串,例如

String a= data 
String b = structures 

If use perform strcat

如果使用执行 strcat

Strcat(a, b) 

then

然后

a= data structures

But if you want to concatenate specific numer of word r elements then you can use strncat Example if you want to concatenate only the first two alphabet lts of b into a then you have to write Strncat(a,b,2) (It means that you just cancatenate the fist two alphabets of b into a , and a becomes a = data st

但是如果你想连接特定数量的单词 r 元素,那么你可以使用 strncat Example 如果你只想将 b 的前两个字母 lts 连接到 a 那么你必须写 Strncat(a,b,2) (这意味着你只需将 b 的前两个字母组合成 a , a 变成 a = data st