c - 'strncpy' 与 'sprintf'

标签 c printf strncpy

我可以在我的应用程序中看到许多用于复制字符串的 sprintf

我有一个字符数组:

char myarray[10];
const char *str = "mystring";

现在如果我想将字符串 str 复制到 myarray 中,最好使用:

sprintf(myarray, "%s", str);

strncpy(myarray, str, 8);

?

最佳答案

两者都不应该使用。

  1. sprintf 是危险的,已弃用并被 snprintf 取代。将旧的 sprintf 安全地用于字符串输入的唯一方法是在调用 sprintf 之前测量它们的长度,这是丑陋且容易出错的,或者通过添加字段精度说明符(例如 %.8s%.*s 以及用于大小限制的额外整数参数)。这也很丑陋且容易出错,尤其是当涉及多个 %s 说明符时。

  2. 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/

相关文章:

c - #if defined(WIN32) 和 #ifdef(WIN32) 的区别

c - 这个最大公约数算法是如何工作的?

对传递引用感到困惑

gcc - 在扩展内联 ASM 中调用 printf

linux - RRDTool GPRINT 格式与 printf

具有多个可选参数的 c 宏

c - strlen 没有产生正确的数字并且 strncpy 不起作用

c++ - 从 C/C++ 播放声音的最简单方法

c - 我的字符串连接每次结果都会加倍,为什么?

c++ - 使用 G++ 编译器的 strncpy_s