为什么它适合缓冲区的大小在C++中使用 sprintf 时很小
Why it is right for buffer's size is small when using sprintf in C++
#include <cstdio>
#include <iostream>
using namespace std;
int main ()
{
char buffer [1];
sprintf (buffer, "%d is one number", 1);
cout<<buffer<<endl;
return 0;
}
buffer
的尺寸只有一个,但cout
可以打印正确的结果。为什么?
这样做安全吗?或者我不得不考虑在使用相关方法时为缓冲区设置一个大大小char *
?
不,这不安全。
C 样式字符串需要以 null 结尾,但 buffer
中没有足够的空间。未定义的行为并不意味着保证工作或不工作。当我测试您的程序时,我遇到了分段错误。
正如余浩所说:不安全!但是为什么它有时会起作用?
char buffer[1]
不是托管阵列。它只是给编译器一个提示,他应该为一个字符保留空间。 变量缓冲区用作指向该空间的指针,并丢失有关原始大小的所有信息。所以上面的陈述和写作是一样的:
char bufferVar = ' '; /* a single character */
char *buffer = &bufferVar; /* a pointer to bufferVar */
缓冲区只包含一个字符的地址,但根本没有其他信息!你的 sprintf 期望这样的地址,一个快乐的写入它的字符串从缓冲区开始。
分段错误是来自操作系统的消息。您的进程为一个字节分配空间。操作系统以页(段(为单位管理内存。当您越过这些段的边界时,将引发分段错误。据我所知,变量是在段的开头还是结尾分配取决于编译器。
余浩的编译器显然把它们放在最后——你的在前面。因此,您的冲刺不会覆盖段的边界。
希望对您有所帮助。
至于考虑存储char *
字符串所需的大小,许多 C stdlib 字符串函数会告诉您如果将它们传递NULL
它们所需的长度。您可以在为字符串分配存储之前调用它,以了解您需要多少存储空间:
std::cout << "You need a buffer that can store "
<< sprintf (NULL, "%d is one number", 1) + 1
<< " characters to safely store your string."
<< std::endl;
另一种解决方案是使用 snprintf (...)
,这保证它会截断输出,使其不会溢出缓冲区:
snprintf (buffer, 1, "%d is one number", 1);
// ~~~
// Length of buffer
在您的情况下,缓冲区只有 1 个字符长,因此它只有足够的空间来存储 null 终止符;不是特别有用。
相关文章:
- 使用 sprintf 将十六进制0xAABBCC转换为字符串"AA:BB:CC"
- 高精度双精度的 Sprintf 格式化问题
- sprintf(b, "%" ) 是否定义了?
- 使用 sprintf 追加到字符数组
- redefine printf(), sprintf(), etc. arm-none-eabi toolchain
- 使用 sprintf 和 %g 将双精度转换为字符串的意外结果
- C++我应该用什么来保存格式化为字符串变量(如sprintf())的文件
- 有没有办法自动实现 sprintf 的缓冲区分配?
- 在 sprintf 中从 'signed char*' 到 'char*' 的转换无效
- 需要将 sprintf 格式加倍并返回太长的字符串
- 代码中的"sprintf"用法是否需要释放内存?
- 使用 sprintf 和 sscanf 将给定数字中的所有 0 替换为 5
- sprintf() 正在添加一个额外的变量
- 对 sprintf 可变参数使用一个指针
- 如何使用sprintf将UINT_64的数组添加到一个字符数组中
- 在 sprintf 函数中添加逗号
- 定义char数据类型,并与sprintf一起使用
- 如何在C++03中用sprintf正确地替换sprintf_s
- Sprintf 缓冲区问题,错误分配给字符数组
- UTF-8, sprintf, strlen, etc