整数作为char * for dummies

时间:2011-07-29 13:04:25

标签: c++ string integer itoa

问题一直在问,但我仍然有点不知道最好的方法。我有一个整数,并希望获得一个char *作为结构的成员。

类似的问题就是例如 herehere。  我宁愿不使用stringstream或lexical_cast。据我所知,基本上留下itoa,sprintf和snprintf。

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

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

2 个答案:

答案 0 :(得分:2)

  

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

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

  

我认为已经分配了内存?

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

  

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

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

因此,如果您想让str保持一些(以null结尾的)字符串值,您将执行以下操作:

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位数),你可以这样做,但通常更容易给出最大可能的长度,因为最后你只会浪费几个字节string,这不是什么大问题,除非你有一些非常严格的内存限制。

  

是否推荐了snotof而不是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都将为您终止字符串。

答案 1 :(得分:0)

如果您确实不想使用std::stringstreamlexical_cast,则应使用snprintf,因为它具有缓冲区大小参数。 itoa不是ISO C函数。

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

说你有像

这样的东西
char str[] = { 'a', 'b', 'c', '\0', 'd' };

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

数组(或任何其他原始数据类型)没有构造函数或析构函数。如果您使用newnew[]malloc或类似内容自行分配内存,则只需担心释放已分配的内存。

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

最佳选择是使用std::stringstreamstd/boost::lexical_caststd::string,它会为您解决所有这些问题。

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