检查以下简单C程序:
#include <stdio.h>
int main(void)
{
char str[4] = {1, 1, 1, 1};
snprintf(str, sizeof(str), "%s%s", "a", NULL);
printf("%s\n", str);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
构建并运行它Linux:
$ gcc test.c
$ ./a.out
a(n
Run Code Online (Sandbox Code Playgroud)
如何理解输出中(n出现的" "字符a?我希望当snprintf遇到NULL争论时,它会停止处理.顺便说一下,我无法从snprintf 手册中找到相关信息.
AnT*_*AnT 10
如果snprintf(fprintf,printf或从该系列中的任何功能)遇到一个空指针参数的%s格式说明,该行为是不确定的.在现实生活中,不是崩溃或行为不可预测,许多标准库实现更喜欢将(null)序列插入到收件人缓冲区中.这是你在实验中观察到的东西-那开始(null)是snprintf成功地适应这个的剩余空间str受主阵列.
很久以前有一个故事(即使互联网,它永远不会忘记,似乎已经忘记了它),关于一家大型美国电信公司的普通客户,他将"null"注册为他的电子邮件ID,因此获得"null @" company.com"作为他的电子邮件地址.突然,他开始收到大量内部公司的电子邮件,其中包含其他客户的个人数据.如果我没记错的话,它是由内部公司软件中的一个错误引起的,其中一个空指针被传递给负责形成目标电子邮件地址的函数.而且该函数不是崩溃,而是采用类似的故障安全行为来响应空指针参数.在有人将"null@company.com"注册为有效的电子邮件地址之前,该错误一直未被发现.
该snprintf函数尝试写入"(null)"您的字符串,但由于目标只有四个字符,因此您永远不会获得超过三个字符的字符串(加上终结符).
请注意,插入"(null)"不是由标准指定的,为"%s"格式说明符传递NULL参数实际上是未定义的行为.