1

我只想使用 studio.h 库通过使用数组存储余数将十进制数转换为二进制数但结果不正确,可能是我的内存分配有问题或返回值错误,请帮我检查一下. 太感谢了!

#include <stdio.h>
int  n = 0;
int* DecimalToBinary(int number){
    int a[10];      
    while(number!=0){
        a[n++] = number%2;
        number/=2;
    }
    return a;
}

void main(){

    int *d1 = DecimalToBinary(5);
    int *d2 = DecimalToBinary(10);

    for(int i = n-1 ;i>=0;i--)
        printf(" %d",d1[i]);

    printf("\n");

    for(int i = n-1 ;i>=0;i--)
        printf(" %d",d2[i]);

}
4

6 回答 6

8

您返回一个指向本地数组的指针。该本地数组位于堆栈上,当函数返回时,数组超出范围,并且在调用下一个函数时将重用该堆栈内存。这意味着指针现在将指向一些其他数据,而不是原始数组。

有两种解决方案:

  1. 在函数调用 DecimalToBinary中声明数组并将其作为参数传递。
  2. 在堆上动态创建数组(例如使用malloc)并返回该指针。

方法 2 的问题是,如果不free返回指针,它可能会造成内存泄漏。


正如 Craig 所指出的,还有第三种解决方案,即static在函数内部创建数组。但是在这种情况下,它带来了比我最初列出的两个解决方案更大的问题,这就是我没有列出它的原因。

正如 Uchia Itachi 所指出的,代码还有另一个严重的问题,那就是数组是由全局变量索引的。如果DecimalToBinary函数被调用的数字太大,或者被调用多次,这个全局索引变量对于数组来说太大了,并且超出了数组的范围。

取消引用指向超出范围数组的指针和超出范围的索引都会导致未定义的行为。如果幸运的话,未定义的行为只会导致打印错误的结果。如果你不走运,它会导致程序崩溃。

于 2013-08-06T07:34:58.583 回答
3

您正在返回一个指向本地分配数组的指针。它在堆栈上分配,并在函数返回时消失,使您的指针指向垃圾。

你有几个选择。你可以传入一个数组来填充:

void DecimalToBinary(int result[10],int number){
    while(number!=0){
        result[n++] = number%2;
        number/=2;
    }
    return result;
}

// usage example:
int b[10];
DecimalToBinary(b, 42);

或者你可以在堆上分配一个数组:

int* DecimalToBinary(int number){
    int *a = (int *)malloc(sizeof(int) * 10);
    while(number!=0){
        a[n++] = number%2;
        number/=2;
    }
    return a;
}

// usage example
int *b = DecimalToBinary(42);
free(b); // when finished with it

或者您可以将数组包装在一个结构中:

typedef struct {
    int b[10];
} result;

result DecimalToBinary(int number){
    result r;
    while(number!=0){
        r.b[n++] = number%2;
        number/=2;
    }
    return r;
}

// usage example
result r = DecimalToBinary(42);

如果您使用 malloc() 选项,请不要忘记在完成后释放返回的数据,否则它会挂起。这称为内存泄漏。在更复杂的程序中,它可能会导致严重的问题。

注意:顺便说一句,如果您的数字大于 1023(10 个二进制数字),您将超出数组。您可能还希望在存储 10 位后显式停止,或者传入数组的大小,或者先计算所需的大小并分配那么多空间。此外,如果您的数字为负数,您会得到一些奇怪的结果,您可能想要使用number&1而不是number%2.

注意 2:如其他地方所述,您应该将n其设为本地,或者至少在每次调用该函数时将其重新初始化为 0,否则它只会累积,最终您将超过数组的末尾。

于 2013-08-06T07:37:53.263 回答
1

int[10]不一样int *; 前者不仅是在堆栈上创建的,而且是完全不同的类型。您需要int *像这样创建一个实际的:

int *a = malloc (10 * sizeof (int));

当然,用完后别忘了free()

于 2013-08-06T07:36:12.557 回答
0

您的代码中的问题出在此处..

int * DecimalToBinary(int number){
int a[10];      
while(number!=0){
    a[n++] = number%2;
    number/=2;
}
return a;

}

范围数组仅在此函数之前。一旦此函数终止,分配给此数组的内存将被释放,您需要使用动态内存分配或将数组设为全局。

于 2013-08-06T07:58:13.370 回答
0

您还可以做什么以及在 C 中通常做什么是在调用它的位置创建数组,并向该函数提供指向该数组的指针,这样当数组位于调用它的函数的堆栈上而不是在发挥自我。我们还必须在该函数上指定数组的大小,因为该函数无法知道指针指向多少个元素

void DecimalToBinary( int number, int* output, unsigned size ) {
    /*adapt this to your liking*/
    int i;
    for ( i = 0; i < size && number != 0; i++) {
        output[i] = number%2;
        number/2;
    }
}

在你的 main 函数中,你会这样称呼它:

int array[10];
DecimalToBinary( 5, array, sizeof(array)/sizeof(array[0]));

a现在数组的结果与您的示例中的结果相同。

于 2013-08-06T07:53:56.350 回答
-1

这是正确的程序:

#include <stdio.h>
int  n = 0;
int a[10] = {0};
int* DecimalToBinary(int number){
    n = 0;     
    while(number!=0){
        a[n++] = number%2;
        number = number/2;
    }
    return a;
}

int main(){

    int *d1;
    int *d2;
    int i;
    d1 = DecimalToBinary(5);
    for(i = n-1;i>=0;i--)
        printf(" %d",d1[i]);
    printf("\n");
    d2 = DecimalToBinary(10);
    for(i = n-1;i>=0;i--)
        printf(" %d",d2[i]);
    printf("\n");
}
于 2013-08-06T08:02:44.250 回答