【问题标题】:Cannot return int array无法返回 int 数组
【发布时间】:2013-08-06 07:32:33
【问题描述】:

我只想使用 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]);

}

【问题讨论】:

  • “结果不正确”——以什么方式?
  • 变量a在堆栈上声明,离开该函数时超出范围!
  • 讲座为什么你不能这样做eskimo.com/~scs/cclass/int/sx5.html
  • 标准函数itoa做你想做的事; this 实现使用 static 数组来正确执行此操作(在代码中查找 static 以了解如何操作)。
  • void main() 是懒惰的编程。使用int main()

标签: c arrays


【解决方案1】:

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

有两种解决方案:

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

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


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

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

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

【讨论】:

  • 还有第三种解决方案,就是将a声明为static。这确实会产生一个问题,即您不能多次使用此函数,或者如果这样做,您必须首先复制上一个函数调用中的值。
  • 代码中还有一个错误。在函数中将全局n 重新初始化为0 怎么样?每次数组从不同的位置开始填充,并在几次函数调用后最终超出范围..
  • 第四种解决方案是使用全局数组。
  • @UchiaItachi 使用全局数组会导致与使用static 本地数组相同的问题。
  • 哦,还有一个选择是将数组粘贴到结构中并返回它。它的好处是不必担心 free()。
【解决方案2】:

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

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

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&amp;1 而不是 number%2

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

【讨论】:

  • 请注意,在void DecimalToBinary(int result[10],int number) 中,“10”将被忽略,数组被提升为数组。所以实际上,签名将是void DecimalToBinary(int *result, int number)
  • 我喜欢在自我说明文件中包含尺寸。只是个人喜好,没有其他真正的原因。
【解决方案3】:

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

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

当然,使用后别忘了free()哦!

【讨论】:

    【解决方案4】:

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

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

    在你的主函数中你可以这样称呼它:

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

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

    【讨论】:

      【解决方案5】:

      你的代码问题出在这里..

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

      }

      作用域的数组只到这个函数。一旦这个函数终止,分配给这个数组的内存将被释放,要么你需要使用动态内存分配,要么将数组设为全局。

      【讨论】:

        【解决方案6】:

        这是正确的程序:

        #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");
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-06-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-05-27
          • 2019-07-12
          • 1970-01-01
          相关资源
          最近更新 更多