0

以前一直在问问题,但我对最好的方法还是有点茫然。我有一个整数,想获得一个 char* 用作结构的成员。

类似的问题例如 在这里这里。我宁愿不使用 stringstream 或 lexical_cast。据我所知,基本上只剩下 itoa、sprintf 和 snprintf。

我想我的部分问题是我不太清楚 char 指针是如何工作的。

  1. 如果我请求 a char str[12],那保留 12 个字符?
  2. 我认为内存已被分配?
  3. 那么空终止是如何工作的呢?
  4. 是在 12 个字符的末尾(有空格填充?),或者如果数字只使用 2 个字符,它会在两个字符之后发生吗?
  5. 缓冲区大小是否重要,或者我应该使用某个最大值(我相信 32 位为 30 左右)?
  6. 如果我稍后在一个简单的结构中使用指针,内存会自动清除还是需要析构函数?
  7. 析构函数是否需要知道初始化缓冲区的大小?
  8. 为什么没有人费心根据实际数字计算缓冲区长度?
  9. 是否推荐 snprintf 而不是 itoa?

谢谢

4

2 回答 2

2

如果我请求一个 char str[12],那保留 12 个字符?

是的,这在堆栈上保留了 12 个字符(字节)。

我认为内存已被分配?

str现在指向已在堆栈上分配的 12 个字节的连续内存的开头。

那么空终止是如何工作的呢?是在 12 个字符的末尾(有空格填充?),或者如果数字只使用 2 个字符,它会在两个字符之后发生吗?

在这种情况下,您必须自己对字符串进行空终止(这种类型的声明不会自动发生)。

因此,如果您想str保留一些(以空结尾的)字符串值,您可以执行以下操作:

str[0] = 'c';
str[1] = 'a';
str[2] = 't';
str[3] = '\0';

获取以 null 结尾的字符串的另一种方法是执行以下操作:

char *str = "cat"; // this is null-terminated

没有自动填充空格。

如果我稍后在一个简单的结构中使用指针,内存会自动清除还是需要析构函数?

如果指针指向的是分配在栈上的一块内存,那么出栈时内存会被回收。否则,如果您在堆上分配内存,例如:

char *newStr    = new char[12];
char *mallocStr = (char*) malloc(sizeof(char) * 12);

然后,您将不得不使用deletefree(取决于您使用的方法)取消分配内存。

析构函数是否需要知道初始化缓冲区的大小?

在这种情况下,我们谈论的是堆分配内存,因此答案是否定的。系统知道分配了多少内存。这就是为什么您只需提供指针deletefree无需提供大小。

为什么没有人费心根据实际数字计算缓冲区长度?

如果您知道您的号码永远不会超过一定数量(例如 4 位数字),则可以,但通常只给出可能的最大长度会更容易,因为最后您只会浪费每个字符串的几个字节,这除非您有一些非常严格的内存限制,否则这没什么大不了的。

是否推荐 snprintf 而不是 itoa?

我会说是,因为snprintf它被认为是“安全的”,因为它尊重你给它的缓冲区大小,而itoa会很高兴地填充你的缓冲区而不检查它的大小(可能运行超过分配的空间并覆盖其他内存)。

int   num = 12345;
char *str = new char[4];

// this is bad because str is not big enough to hold the number
// itoa does not check buffer size and will overrun the buffer (overwriting other data)
str = itoa(num, str);

// snprintf takes the buffer size as one of it's arguments
// in this case the whole number will not fit, but at least we don't overrun the buffer
snprintf(str, 4, "%i", num);

两者snprintfitoa都会为您终止字符串。

于 2011-07-29T13:40:09.253 回答
0

如果你真的不想使用std::stringstreamor lexical_cast,你应该使用snprintf,因为它有一个缓冲区大小参数。itoa不是 ISO C 函数。

Null(字符 '\0',值 0)可以出现在缓冲区中的任何位置,大多数处理字符串的函数都会忽略该点之后缓冲区中的所有内容,因此它有点“浪费”空间。

假设你有类似的东西

char str[] = { 'a', 'b', 'c', '\0', 'd' };

即使函数printf遇到 0 时停止处理数据,最后一个元素仍然存在。但并非每个函数都这样做。

数组(或任何其他原始数据类型)没有构造函数或析构函数。new如果您使用,或类似的东西自己分配它new[],您只需要担心释放分配的内存。malloc

缓冲区大小当然很重要,如果它太小就无法容纳数字的每个字符,如果它太大,就会浪费内存。22 个字符应该能够容纳每个 64 位整数(但不能容纳浮点数/双精度数!)。

最好的选择是使用std::stringstreamor std/boost::lexical_castand std::string,它会为您解决所有这些问题。

我建议您阅读 Martinho 的链接,非常有用。(数组不是指针!)

于 2011-07-29T13:39:39.513 回答