对于傻瓜来说,整数作为 char*

发布于 2024-11-27 05:53:39 字数 787 浏览 2 评论 0原文

之前已经问过这个问题,但我仍然对最好的方法感到有点茫然。我有一个整数,想要获取一个 char* 来用作结构体的成员。

类似的问题例如 此处此处。 我不想使用 stringstream 或 lexical_cast。据我所知,基本上只剩下 itoa、sprintf 和 snprintf。

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

  1. 如果我请求一个 char str[12],它会保留 12 个字符吗?
  2. 我认为内存已经被分配了?
  3. 那么空终止是如何工作的呢?
  4. 是在 12 个字符的末尾(用空格填充吗?),还是 如果号码只使用2个字符,那么会在两个字符之后发生吗?
  5. 缓冲区大小重要吗还是我应该使用一些最大值 (我相信对于 32 位来说是 30 个左右)?
  6. 如果我稍后在一个简单的结构中使用指针,内存会 会自动清除还是需要析构函数?
  7. 析构函数是否需要知道初始化缓冲区大小?
  8. 为什么没有人费心去计算缓冲区长度 实际数量?
  9. 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.

  1. If I request a char str[12], that reserves 12 characters?
  2. I presume that memory has then been assigned?
  3. So how does null termination work?
  4. 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?
  5. Does the buffer size matter or should I just go with some maximum
    (30 or so I believe for 32 bits)?
  6. And if I use the pointer later in a simple struct, will the memory
    be cleared automatically or do I need a destructor?
  7. Does the destructor need to know the initialize buffer size?
  8. Why does no one bother to calculate the buffer length from the
    actual number?
  9. Is snprintf recommended over itoa?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

橘和柠 2024-12-04 05:53:39

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

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

我认为内存已经被分配了?

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

那么空终止是如何工作的呢?是在 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 位数字),则可以,但通常更容易给出最大可能的长度,因为最终您只会浪费每个字符串的几个字节,这除非你有一些非常严格的内存限制,否则没什么大不了的。

是否推荐使用 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 都会为您终止字符串。

If I request a char str[12], that reserves 12 characters?

Yes, this reserves 12 characters (bytes) on the stack.

I presume that memory has then been assigned?

str now points to the beginning of 12 bytes of contiguous memory that has been allocated on the stack.

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?

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:

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

Another way to get a null-terminated string is to do the following:

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

There is no automatic padding with spaces.

And if I use the pointer later in a simple struct, will the memory be cleared automatically or do I need a destructor?

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:

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

Then you will have to de-allocate the memory using delete or free (depending on which method you used).

Does the destructor need to know the initialize buffer size?

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 and free without having to provide a size.

Why does no one bother to calculate the buffer length from the actual number?

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.

Is snprintf recommended over itoa?

I would say yes because snprintf is considered "safe" because it respects the buffer size that you give it, whereas itoa will happily fill your buffer without checking its size (possibly running past the allocated space and overwriting other memory).

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);

Both snprintf and itoa will null-terminate the strings for you.

晌融 2024-12-04 05:53:39

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

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

假设您有一个类似于

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

“最后一个元素”的东西,即使像 printf 这样的函数在遇到 0 时停止处理数据。但并非每个函数都会这样做。

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

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

最好的选择是使用 std::stringstream 或 std/boost::lexical_cast 和 std::string ,它会照顾所有这些问题为您解答。

我建议您阅读 Martinho 的链接,内容非常丰富。 (数组不是指针!)

If you really don't want to use std::stringstream or lexical_cast, you should use snprintf 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

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

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 or std/boost::lexical_cast and std::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!)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文