I'm new to C, and trying to understand why the following works with a fixed-size character array but not with a pointer:
float number = 1245.12;
// allocate a character array for the buffer
char number_as_string[50];
sprintf(number_as_string, "%f", number);
But allocating a pointer (which I thought would point to a location in memory, and allow iterating to the next memory point, etc.) would not work:
float number = 1245.12;
// allocate a pointer
char * number_as_string;
sprintf(number_as_string, "%f", number);
I'm going to answer your question in two parts.
You wrote
float number = 1245.12;
char number_as_string[50];
sprintf(number_as_string, "%f", number);
That's fine and will work, although of course one problem with fixed-size buffers like these is that it's easy to overflow them, sometimes with catastrophic results. So a preferred alternative is
snprintf(number_as_string, sizeof(number_as_string), "%f", number);
snprintf
is a variant of sprintf
that lets you specify the size of the buffer. That way, snprintf
can take care not to write more characters to the buffer than it will hold.
So now let's see about using snprintf
with your second example:
char *number_as_string;
snprintf(number_as_string, ???, "%f", number);
But what size do we use? How big is the buffer pointed to by this second number_as_string
? We don't know, and this helps us realize that we haven't yet allocated a buffer for the second number_as_string
to point to at all.
What you want to do is use malloc
to allocate some memory for number_as_string
to point to:
number_as_string = malloc(50);
Now, and assuming malloc
succeeds, you know what number to hand to snprintf
as the buffer size:
snprintf(number_as_string, 50, "%f", number);
Realistically, of course, we'd have a variable holding the allocated buffer size, rather than repeating the number "50" in multiple places. So here's the more realistic example, including the test to make sure malloc
didn't fail:
int buffer_size = 50;
char *number_as_string = malloc(buffer_size);
if(number_as_string == NULL) {
fprintf(stderr, "out of memory\n");
exit(1);
}
snprintf(number_as_string, buffer_size, "%f", number);
Just make sure you don't do:
snprintf(number_as_string, sizeof(number_as_string), "%f", number);
when number_as_string
is a pointer. In that case, you'll get the size of the pointer (typically 4 or 8 bytes, these days), not the size of the pointed-to buffer, which is what you want.
I like to understand memory allocation, and pointers, with little box-and-arrow diagrams. Here's char number_as_string[50]
:
+--+--+--+--+--+--+--+--+--+--+--+--+--+ +--+--+
number_as_string: | | | | | | | | | | | | | |...| | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+ +--+--+
Here's char *number_as_string
followed by a successful number_as_string = malloc(50)
:
+-------+
number_as_string: | * |
+---|---+
|
v
+--+--+--+--+--+--+--+--+--+--+--+--+--+ +--+--+
| | | | | | | | | | | | | |...| | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+ +--+--+
But here's char *number_as_string
all by itself:
+-------+
number_as_string: | *--------> ???
+-------+
The arrow -- the pointer -- points "nowhere".
A pointer variable needs something to point to, and in your second example number_as_string
doesn't point to anything. Attempting to dereference it via a call to sprintf
invokes undefined behavior .
You need to either allocate space dynamically:
char * number_as_string = malloc(50);
Or make it point someplace valid:
char str[50];
char * number_as_string = str;
In the first case
char number_as_string[50];
sprintf(number_as_string, "%f", 123.456);
you have an automatic-storage variable that is an array of 50 char
s. This array is usualy on the stack, so when you call sprintf()
, you are "printing" on valid memory.
In the second case
char * number_as_string;
sprintf(number_as_string, "%f", 123.456);
you also have an automatic variable. However this variable is only a pointer. You did not ask the compiler for an array. Furthermore, you didn't initialize the pointer, so you cannot even tell whether sprintf()
will even receive a memory location that belongs to your program.
This is what you are looking for:
char * number_as_string = malloc(50);
sprintf(number_as_string, "%f", 123.456);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.