我可以在我的应用程序中看到许多用于复制字符串的 sprintf
。
我有一个字符数组:
char myarray[10];
const char *str = "mystring";
现在如果我想将字符串 str
复制到 myarray
中,最好使用:
sprintf(myarray, "%s", str);
或
strncpy(myarray, str, 8);
?
最佳答案
两者都不应该使用。
sprintf
是危险的,已弃用并被snprintf
取代。将旧的sprintf
安全地用于字符串输入的唯一方法是在调用sprintf
之前测量它们的长度,这是丑陋且容易出错的,或者通过添加字段精度说明符(例如%.8s
或%.*s
以及用于大小限制的额外整数参数)。这也很丑陋且容易出错,尤其是当涉及多个%s
说明符时。strncpy
也很危险。它不是strcpy
的缓冲区大小限制版本。它是一个函数,用于将字符复制到固定长度的空填充(相对于空终止)数组,其中源可以是 C 字符串或定长字符数组至少是目标的大小。它的预期用途是遗留的 unix 目录表、数据库条目等,它们使用固定大小的文本字段,并且不想在磁盘或内存中浪费一个字节以用于空终止。它可以被误用为缓冲区大小受限的strcpy
,但这样做是有害的,原因有二。首先,如果整个缓冲区都用于字符串数据(即如果源字符串长度至少与目标缓冲区一样长),则它无法终止 null。您可以自己添加终止符,但这很丑陋且容易出错。其次,当源字符串比输出缓冲区短时,strncpy
总是用空字节填充完整的目标缓冲区。这简直是浪费时间。
那么您应该改用什么?
有些人喜欢 BSD 的 strlcpy
函数。从语义上讲,它与 snprintf(dest, dessize, "%s", source)
相同,只是返回值是 size_t
并且它不强加人为的 INT_MAX
字符串长度限制。然而,大多数流行的非 BSD 系统都缺少 strlcpy
,并且很容易在自己编写时出现危险的错误,因此如果您想使用它,您应该从可信赖的公司获得一个安全、已知的工作版本来源。
我的偏好是简单地使用 snprintf
进行任何重要的字符串构造,而 strlen
+memcpy
用于一些已被测量为对性能至关重要。如果您养成了正确使用这个习语的习惯,那么不小心编写带有字符串相关漏洞的代码几乎是不可能的。
关于c - 'strncpy' 与 'sprintf',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12275381/