Integer number as char* for dummies
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 ove开发者_JAVA技巧r itoa?
Thanks
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.
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!)
精彩评论