簡體   English   中英

從C函數返回數組

[英]Returning Array from function in C

出於某種原因,我的函數僅返回數組中的第一個元素,而我無法弄清數組其余部分為何超出范圍。 該函數采用兩個整數數組,將它們各自的元素相加,然后將總和放入返回的第三個數組中。

這是我的代碼:

#include <stdio.h>
/* count digits, white space, others */

int *sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len);

void main() {

    int arr1[10];
    size_t arr1len = 10;
    int arr2[10] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 };
    size_t arr2len = 10;
    int i;

    int *x;

    arr1[0] = 2;
    arr1[1] = 3;
    arr1[2] = 2;
    arr1[3] = 2;
    arr1[4] = 2;
    arr1[5] = 2;
    arr1[6] = 3;
    arr1[7] = 2;
    arr1[8] = 2;
    arr1[9] = 2;

    //printf("%d\t%d\t%d\n", arr1, *arr1, *(arr1 + 1));
    x = sumarrays(arr1, arr1len, arr2, arr2len);

    for (i = 0; i < 10; i++) {
        printf("Array1: %d\tArray 2: %d\tX = %d\n", arr1[i], arr2[i], x[i]);

    }

    //return 0;
}

int *sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len) {
    int i;
    int total[10];

    for (i = 0; i < 10; i++) {
        total[i] = *(arr1 + i) + *(arr2 + i);

    }
    for (i = 0; i < 10; i++) {
        printf("%d\t", total[i]);
    }

    printf("\n");
    return total;
}

這是輸出:

4   5   4   4   4   4   5   4   4   4   
Array1: 2   Array 2: 2  X = 4
Array1: 3   Array 2: 2  X = 1974388256
Array1: 2   Array 2: 2  X = -161927102
Array1: 2   Array 2: 2  X = 2686628
Array1: 2   Array 2: 2  X = 8670801
Array1: 2   Array 2: 2  X = 0
Array1: 3   Array 2: 2  X = 27
Array1: 2   Array 2: 2  X = 2686540
Array1: 2   Array 2: 2  X = 4
Array1: 2   Array 2: 2  X = 2686916

第一行是函數內部的求和數組元素。 剩下的就是main()中發生的事情。

我想念什么?

*編輯* ANSWERED

謝謝大家的幫助! 我實際上是前一段時間學習過C和C ++的,但是最近開始回過頭來微調我的知識。 真的感謝所有幫助。

主要的答案是

1)靜態分配內存(使用static關鍵字)

2)動態分配內存(使用malloc())

3)將變量設為全局

4)將結果total()作為參數傳遞給函數,這樣它就不會超出范圍。

您正在為數組進行堆棧分配,並且當函數返回時,堆棧分配的存儲將消失。 請改用堆分配。

更改

int total[10];

int* total = malloc(10*sizeof(int))

當然,這意味着您還必須在完成處理后free內存。 在這種情況下,在return 0;之前return 0; 總的來說,你需要

free(x);

我的函數僅返回數組中的第一個元素,而我無法弄清數組其余部分為何超出范圍。

不,它返回指向第一個元素的指針- 整個數組超出范圍。 您看到的任何碰巧保留在函數中的數據都是靠運氣而不是判斷,您不能使用它,因為它已發布供其他函數使用。

數組不是C語言中的一流數據類型 -您不能通過副本返回數組。

通常的解決方案是讓調用者擁有該數組,並將其地址和大小傳遞給該函數。

int* func( int* arr, int arrlen )
{
    // write to arr[0] to arr[arrlen-1] ;

    return arr ;
}

int main()
{
    int array[256] ;
    func( array, sizeof(arr)/sizeof*(*arr) ) ;
}

其他不太常見且通常不建議使用的可能性是返回包含數組的結構(結構是第一類數據類型),但是這樣做在許多情況下效率低下,或者在函數內動態分配數組,但這不是一個特別好的主意,因為調用者有責任釋放該內存,並且可能不知道該職責-這是導致內存泄漏的原因。

您不能返回指向自動局部變量的指針。 total是一個自動局部變量,在函數體執行后不存在。

可以返回指向static局部變量或動態分配的變量的指針。 更改
int total[10];

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

問題在於,當sumarrays返回時, total組將不再存在 1 ,因此main接收的指針值不再有效。 簡而言之,您不能從這樣的函數返回數組。

您有幾種選擇。

第一個(首選IMO是IMO)是將total組作為您的參數之一傳遞,並讓調用方負責預留足夠的內存:

void sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len, int *total, size_t totallen) 
{
  ...
  for (i = 0; i < totalLen; i++) {
      total[i] = *(arr1 + i) + *(arr2 + i);
  ...
}

#define ARRLEN 10

int main( void )
{
  ... 
  int x[ARRLEN];
  ...
  sumarrays( arr1, ARRLEN, arr2, ARRLEN, x, ARRLEN);

在此方法中,調用方( main )負責知道目標數組需要多大,並為其預留內存。 幫助可以 sumarrays函數與main 分離 ,因為它不必依賴未由參數列表明確指定的信息(例如數組大小)。 使用這種方法,您不僅限於大小為10的數組。

第二種選擇是聲明total ,以使sumarrays退出后不會消失。 您可以通過在文件范圍內聲明它(如ryyker的回答),或在sumarrays函數中聲明它為static來做到這一點:

int *sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len) {
    int i;
    static int total[10];
    ...

使用這種方法, total數組將在程序啟動時分配並保留,直到程序終止。 使此方法變得不太理想的原因是,您只有該total組的單個實例,該實例在對sumarrays所有調用中sumarrays 該功能不再可重入 如果sumarrays調用了另一個函數調用sumarrays ,則無論是第一個調用寫入total都會被第二個調用所破壞( strtok庫函數存在此問題,這在過去引起了很多sumarrays )。 您的代碼顯然沒有這個問題,但是需要注意。 如果沒有必要,不要聲明static東西。

最后一個選項是sumarraystotal內存動態分配內存(如hacks和merlin2011的答案)。 這樣可以避免重新輸入的問題,但是現在您必須處理內存管理。 C不是您的母親,也不會在您之后清理。因此,使用malloccalloc分配的任何內存都必須使用free 2釋放。


1.從邏輯上講,無論如何; 內存顯然仍然存在,但是已經可供系統的其余部分使用,並且在程序返回到main函數所花費的時間內已被覆蓋。

2.大多數平台會在程序退出時回收動態分配的內存,但有些平台(可能是較舊的奇怪的平台)可能不會。 另外,對於長時間運行的程序(服務器,守護程序等),您必須非常小心釋放分配的且不再需要的任何內存,否則最終將用光。

我同意關於自動(堆棧)和堆內存的所有其他答案。 所有好的方法,但是堆棧上的全局變量也是一個選擇 重要的是要注意, 並不是您選擇使用堆棧內存,而是在范圍上它是本地的 局部作用域自動變量在創建它們的函數返回時消失。 但是,全局范圍的變量(也使用堆棧存儲器存儲)在程序運行期間有效,因此提供了另一種方法來解決您的問題...

一行更改將導致您的代碼運行,將本地total (自動范圍)副本更改為全局副本:

int total[10];//Put this here,  outside of any function block in same file, i.e. (will give it global scope)
//note, commented this in function below

int *sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len) {
    int i;
    //int total[10];//move this to global scope


    for (i = 0; i < 10; i++) {
        total[i] = *(arr1 + i) + *(arr2 + i);

    }
    for (i = 0; i < 10; i++) {
        printf("%d\t", total[i]);
    }

    printf("\n");
    return total;
}

使用這種方法 ,變量的全局范圍可以使您的返回成功。 數組total將其保留在堆棧中,直到程序退出。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM