对于傻瓜来说,整数作为 char*
之前已经问过这个问题,但我仍然对最好的方法感到有点茫然。我有一个整数,想要获取一个 char* 来用作结构体的成员。
类似的问题例如 此处或此处。 我不想使用 stringstream 或 lexical_cast。据我所知,基本上只剩下 itoa、sprintf 和 snprintf。
我想我的部分问题是我不太了解 char 指针是如何工作的。
- 如果我请求一个
char str[12]
,它会保留 12 个字符吗? - 我认为内存已经被分配了?
- 那么空终止是如何工作的呢?
- 是在 12 个字符的末尾(用空格填充吗?),还是 如果号码只使用2个字符,那么会在两个字符之后发生吗?
- 缓冲区大小重要吗还是我应该使用一些最大值 (我相信对于 32 位来说是 30 个左右)?
- 如果我稍后在一个简单的结构中使用指针,内存会 会自动清除还是需要析构函数?
- 析构函数是否需要知道初始化缓冲区大小?
- 为什么没有人费心去计算缓冲区长度 实际数量?
- snprintf 是否比 itoa 更推荐?
谢谢
Question has been asking before, but I am still a bit at a loss as to the best way. I have an integer and would like to obtain a char* to use as a member of a struct.
Similar questions are for example
here or here.
I'd rather not use stringstream or lexical_cast. Which as far as I can see basically leaves itoa, sprintf and snprintf.
I guess part of my problem is that I don't quite know how char pointers work.
- If I request a
char str[12]
, that reserves 12 characters? - I presume that memory has then been assigned?
- So how does null termination work?
- Is that at the end of the 12 characters (with spaces padding?), or
if the number only uses 2 characters, would it happen after two? - Does the buffer size matter or should I just go with some maximum
(30 or so I believe for 32 bits)? - And if I use the pointer later in a simple struct, will the memory
be cleared automatically or do I need a destructor? - Does the destructor need to know the initialize buffer size?
- Why does no one bother to calculate the buffer length from the
actual number? - Is snprintf recommended over itoa?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的,这在堆栈上保留了 12 个字符(字节)。
str
现在指向已在堆栈上分配的 12 字节连续内存的开头。在这种情况下,您必须自己以空值终止字符串(这种类型的声明不会自动发生这种情况)。
因此,如果您想让
str
保存一些(以 null 结尾的)字符串值,您可以执行以下操作:获取以 null 结尾的字符串的另一种方法是执行以下操作:
没有自动填充有空格。
如果指针指向栈上分配的一块内存,那么当栈被弹出时,这块内存就会被回收。否则,如果您在堆上分配内存,例如:
那么您将必须使用
delete
或free
(取决于您使用的方法)取消分配内存。在这种情况下,我们讨论的是堆分配的内存,因此答案是否定的。系统知道分配了多少内存。这就是为什么您只需提供指向
delete
和free
的指针,而无需提供大小。如果您知道您的数字永远不会超过一定数量(例如 4 位数字),则可以,但通常更容易给出最大可能的长度,因为最终您只会浪费每个字符串的几个字节,这除非你有一些非常严格的内存限制,否则没什么大不了的。
我会说是,因为
snprintf
被认为是“安全”的,因为它尊重您给它的缓冲区大小,而itoa
会很高兴地填充您的缓冲区而不检查其大小(可能正在运行超过分配的空间并覆盖其他内存)。snprintf
和itoa
都会为您终止字符串。Yes, this reserves 12 characters (bytes) on the stack.
str
now points to the beginning of 12 bytes of contiguous memory that has been allocated on the stack.In this case you have to null-terminate the string yourself (it doesn't automatically happen with this type of declaration).
So if you wanted to make
str
hold some (null-terminated) string value, you would do the following:Another way to get a null-terminated string is to do the following:
There is no automatic padding with spaces.
If the pointer is pointing to a piece of memory allocated on the stack, then the memory will be recovered when the stack is popped. Otherwise, if you allocate memory on the heap such as:
Then you will have to de-allocate the memory using
delete
orfree
(depending on which method you used).In this context we're talking about heap-allocated memory and therefore the answer is no. The system knows how much memory was allocated. That's why you just give the pointer to
delete
andfree
without having to provide a size.You can if you know that your number will never exceed a certain amount (say, 4 digits), but it's usually easier to just give the maximum possible length, because in the end you'll only be wasting a few bytes per string, which isn't a big deal unless you have some really tight memory constraints.
I would say yes because
snprintf
is considered "safe" because it respects the buffer size that you give it, whereasitoa
will happily fill your buffer without checking its size (possibly running past the allocated space and overwriting other memory).Both
snprintf
anditoa
will null-terminate the strings for you.如果您确实不想使用 std::stringstream 或 lexical_cast ,则应该使用 snprintf 因为它有一个缓冲区大小参数。
itoa
不是 ISO C 函数。Null(字符“\0”,值 0)可以出现在缓冲区中的任何点,大多数处理字符串的函数都会忽略该点之后缓冲区中的所有内容,因此它是一种“浪费”的空间。
假设您有一个类似于
“最后一个元素”的东西,即使像
printf
这样的函数在遇到 0 时停止处理数据。但并非每个函数都会这样做。数组(或任何其他基本数据类型)没有构造函数或析构函数。如果您自己使用
new
、new[]
、malloc
或类似的东西分配内存,您只需要担心释放分配的内存。缓冲区大小当然很重要,如果太小,则无法容纳数字的每个字符,如果太大,则会浪费内存。 22 个字符应该能够容纳每个 64 位整数(但不能容纳浮点数/双精度数!)。
最好的选择是使用 std::stringstream 或 std/boost::lexical_cast 和 std::string ,它会照顾所有这些问题为您解答。
我建议您阅读 Martinho 的链接,内容非常丰富。 (数组不是指针!)
If you really don't want to use
std::stringstream
orlexical_cast
, you should usesnprintf
because it has a buffer size argument.itoa
is not an ISO C function.Null (the character '\0', value 0) can appear at any point in the buffer, most functions that work with strings ignore everything in the buffer after that point, so it's sort of "wasted" space.
Say you had a something like
The last element is still there even though functions like
printf
stop processing the data when they encounter 0. Not every function does this though.There is no constructors or destructors for arrays (or any other primitive data types). You only need to worry about releasing the allocated memory if you allocated it yourself using
new
,new[]
,malloc
or something similar.Buffer size matters of course, if it's too small it can't hold the every character of the number, and if it's too large, there's going to be wasted memory. 22 characters should be able to hold every 64 bit integer (but not floats/doubles!).
Best option would be to use
std::stringstream
orstd/boost::lexical_cast
andstd::string
, it would take care of all these issues for you.I suggest you read the link from Martinho, very informative. (Arrays are not Pointers!)