问题
I have a function that returns char* when I print it with printf("%c", *(k+i));
on the main it prints;
0' 10101001 Q -> Q
but if I print with printf(" %c", *(k+i));
there are less problem.
If I print inside the tobinary function, output comes perfect like this;
1010.011010011011101001011110001101010011111101111100111 -> 111011
What Am I doing wrong? here is the code.
char *tobinary(double num) {
int length = 62;
char bin[length];
int intpart = (int)num;
double decpart = 1000*(num - intpart);
int i = 0;
while (intpart!=0) {
if(intpart%2 == 1) bin[3-i] = '1';
else bin[3-i] = '0';
intpart /= 2;
i++;
}
bin[i++] = '.';
while (i <= length) {
decpart *= 2;
if (decpart >= 1000) {
bin[i] = '1';
decpart -= 1000;
}
else bin[i] = '0';
i++;
}
char *k = bin;
return k;
}
int main(int argc, char **argv) {
char *k = tobinary(10.413);
for(int i = 0; i <= 62; ++i) {
printf("%c", *(k+i));
if (i==56) printf(" -> ");
}
}
回答1:
When you declare a local variable in a function, like this
char *tobinary(double num) {
int length = 62;
char bin[length];
/* ... */
}
it is stored in a special memory area called stack. Whenever a function func()
is called, the CPU saves there some useful data such as the address of the calling function where the execution will be restored after func()
returns, along with the parameters of func()
and, as I wrote above, any local variable declared in it.
All this data is stacked with a LIFO criteria (Last In, First Out), so that when function returns a special pointer (stack pointer) is changed to point back to the data regarding the calling function. func()
's data is still there, but it can be overwritten whenever another function is called or other local variables are declared by caller()
. Please note that it is compliant with the fact that local variables have a lifetime limited to the function in which they are declared.
That's what happen in your scenario. Since the execution goes on, your bin[]
array is not guaranted to stay "safe":
int i
is declared in the for-loop sectionprintf()
is called
This is what corrupts "your" data (I used double quotes because it is not yours anymore).
Whenever you need to return data manipulated by a function, you have three options:
- Declare the array outside it and pass it to the function after changing its prototype:
int tobinary(char *arr, unsigned int arrsize, double num);
. In this way the function can modify the data passed by the caller (changing at mostarrsize
characters). The return value can become an error code; something like 0 on success and -1 on failure. - Dynamically allocate the array inside your function using
malloc()
. In this case freeing the memory (withfree()
) is responsability of the caller function. - Declare the array in your function as
static
. This qualifier, in fact, tells the compiler that the lifetime of the variable is the whole life of the program, and a different specific memory area is used to store it instead of the stack. Be aware that in this case your function won't be thread safe anymore (different thread accessing the same memory area would lead to bizarre results).
回答2:
bin is character array inside your function.
It is not static, so when you return a pointer to it, it is not guaranteed to keep the same value.
Either change it to static
or return a memory you allocate and the caller will need to free that memory.
来源:https://stackoverflow.com/questions/62247424/weird-output-behavior-with-char-array-in-c