如果我请求一个 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);
然后,您将不得不使用delete
或free
(取决于您使用的方法)取消分配内存。
析构函数是否需要知道初始化缓冲区的大小?
在这种情况下,我们谈论的是堆分配内存,因此答案是否定的。系统知道分配了多少内存。这就是为什么您只需提供指针delete
而free
无需提供大小。
为什么没有人费心根据实际数字计算缓冲区长度?
如果您知道您的号码永远不会超过一定数量(例如 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);
两者snprintf
和itoa
都会为您终止字符串。