2010-07-16 179 views
0
?? fun() 
{ 
    int a[3]={3,3,4}; 
    return &a; 
} 

什麼可能是兼容的返回類型。這裏的指針指向3個整數的數組,而不僅僅是指向整數數組的指針。 目標是返回一個指向3個整數數組的指針。c語言。函數的返回類型

+3

更好的方法來做到這一點是具有的功能用一個指針指向數組作爲參數,然後有功能填充陣列。 – FrustratedWithFormsDesigner 2010-07-16 14:24:15

+2

gcc甚至沒有-Wall給出「警告:函數返回局部變量的地址」 – Nyan 2010-07-16 14:31:18

回答

0

其他人都已經告訴你爲什麼你不應該這樣做,因爲它是寫的,但這裏有您感興趣的類型。

給出一個聲明int a[3],表達&a的類型是int (*)[3]int **),或「指針3元素數組INT的」,如

void f() 
{ 
    int a[3] = {1,2,3}; 
    int (*aptr)[3] = &a; 
    ... 
} 

以及用於返回該類型的函數的簽名將int (*fun())[3] {...}

另外一個選擇號沒有顯示是這樣的:

int (*fun())[3] 
{ 
    int (*aptr)[3] = malloc(sizeof *aptr); 
    if (aptr) 
    { 
    (*aptr)[0] = 1; // array pointer must be deferenced before applying 
    (*aptr)[1] = 2; // the subscript. 
    (*aptr)[2] = 3; 
    } 
    return aptr; 
} 

雖然這不是非常有用的;你通常不會看到像這樣分配單個固定大小的數組。稍微更有用被分配這些數組的數組:

int (*fun(size_t count))[3] 
{ 
    int (*aptr)[3] = malloc(sizeof *aptr * count); 
    if (aptr) 
    { 
    size_t i; 
    for (i = 0; i < count; i++) 
    { 
     aptr[i][0] = 1; // aptr[i] implicitly dereferences aptr, so 
     aptr[i][1] = 2; // there's no need for an explicit dereference 
     aptr[i][2] = 3; // here. 
    } 
    } 
    return aptr; 
} 

即使這樣,如果有人需要分配一個固定大小的數組類型,他們通常隱藏一個typedef後面:

typedef int fixedSizeRecord[SOME_SIZE]; 
... 
fixedSizeRecord *fun(size_t count) 
{ 
    fixedSizeRecord *aptr = malloc(sizeof *aptr * count); 
    if (aptr) 
    { 
     // initialize contents as necessary 
     for (size_t i = 0; i < count; i++) 
     for (j = 0; j < sizeof *aptr/sizeof *aptr[0]; j++) 
      aptr[i][j] = ...; 
    } 
    return aptr; 
} 

抽象是一個的事。

我已經把這個表的幾個迭代之前;你可能會發現它很方便。

 
Declaration: T a[N]; 

Expression  Type  Decays To  Value 
----------  ----  ---------  ----- 
     a  T [N]  T *    Address of first element in a 
     &a  T (*)[N] n/a    Address of a (same value as above, 
               but different type) 
     *a  T   n/a    Same as a[0] 
     a[i]  T   n/a    Value at index i 
    &a[i]  T *   n/a    Address of value at index i 
    sizeof a  size_t      Total number of bytes in a 
               (N * sizeof T) 
sizeof a/
    sizeof *a  size_t  n/a    Number of elements in a (N) 

Declaration: T a[N][M]; 

Expression  Type  Decays To  Value 
----------  ----  ---------  ----- 
     a  T [N][M] T (*)[M]   Address of first element in a[0] 
     &a  T (*)[N][M] n/a    Address of a (same value as above, 
               but different type) 
     *a  T [M]  T *    Same as a[0] 
     a[i]  T [M]  T *    Address of first element in array 
               at index i 
     &a[i]  T (*)[M] n/a    Address of array at index i (same 
               value as above, but different 
               type) 
     *a[i]  T   n/a    Same as a[i][0] 
    a[i][j]  T   n/a    Value at a[i][j] 
    &a[i][j]  T *   n/a    Address of value at index i,j 
    sizeof a  size_t  n/a    Total number of bytes in a 
               (N * M * sizeof T) 
sizeof a/
    sizeof *a  size_t  n/a    Number of subarrays in a (N) 
sizeof a[i]  size_t  n/a    Total number of bytes in a[i] 
               (M * sizeof T) 
sizeof a[i]/
    sizeof *a[i] size_t  n/a    Number of elements in a[i] (M) 
14

首先,你真的是應該不是返回一個局部變量的地址。當函數退出時,數組a將被破壞。

至於你的問題,&a的類型是int (*)[]

+0

我想多解釋一下(*爲什麼* OP不應該返回地址局部變量,如果他們嘗試會發生什麼),它會*回答問題。 – FrustratedWithFormsDesigner 2010-07-16 14:46:09

+0

你是對的,但OP應該真的考慮到這一點。儘管如此,我仍然遵循你的建議並編輯我的答案。 – 2010-07-16 14:46:44

1

不要犯這個錯誤。只要fun()失去範圍,所有它就是局部變量。

1

本地變量的地址不能從函數返回。 當地變量放在堆棧

3

的類型將是int **

但你的代碼是錯誤的,因爲你的表是在棧上。 從函數返回時,返回堆棧中元素的指針使得引用無處指向。

+2

該類型會衰減到int **,但它最初是一個指向3個整數數組的指針。 – 2010-07-16 14:28:10

+0

該類型不能是'int **';而_array_可能會衰減到一個指針,而指向array_的指針可能不會。 – 2010-07-16 14:35:11

+0

該類型將是指向10個整數數組的指針。 http://c-faq.com/aryptr/aryvsadr.html – Nyan 2010-07-16 14:40:57

0

如果你想返回一個指向數組的指針,不要返回局部變量的地址。你在這裏返回的將是int**。你想要做的是分配一個新的int數組,並返回int*。你想要的可能是這樣的:

int* fun() 
{ 
    int* a = malloc(sizeof(int) * 3); 
    a[0] = 3; 
    a[1] = 3; 
    a[2] = 4; 
    return a; 
} 

然後你需要確保以後釋放分配的數組。

5

不要這樣做。

您正在返回一個指向局部變量的指針。當函數返回時,該指針指向一個不再有效的位置,所以這個練習是毫無意義的。 返回類型本來int (*)[3]雖然,但是當你使用它作爲函數的返回類型,其原型是int (*fun(void))[3](啊,EEW)

然而

如果a是靜態的,你可以做

int (*fun(void))[3] 
{ 
    static int a[3]={3,3,4}; 
    return &a; 
} 

這是比較常見的指針數組中返回的第一個元素 - 但你必須在你可以訪問3個指針的只有3個元素調用者「知道」。

int *fun(void) 
{ 
    static int a[3]={3,3,4}; 
    return &a[0]; // or just return a; 
} 

由於a在這些情況下靜態的,你就不用擔心實現相同的約reentrancy

2比較常見的方式:通過參數數組中

通行證並分配給呼叫者:

void fun(int *a) 
{ 
     a[0] = 3; 
     a[1] = 3; 
     a[2] = 4; 

} 

這樣稱呼它:

int a[3]; 
fun(a); 

動態分配內存:

int *fun(void) 
{ 
    int *a = malloc(3*sizeof *a); 
    if(a) { 
    a[0] = 3; 
    a[1] = 3; 
    a[2] = 4; 
    } 
    return a; 
} 

這樣稱呼它:

int *a; 
a = fun(); 
if(a) { 
    ///use a 
    free(a); // remember to free it when done 
} else { 
    //out of memory 
} 
+0

該標準是否確實保證返回一個指向本地作用域的靜態變量的指針會沒問題?我的意思是,我知道它是如何工作的,所以我無法想象它會如何爆炸。 – detly 2010-07-16 14:57:05

+0

@detly:除了重入以外,沒有任何問題。 – 2010-07-16 14:59:23

0

你的功能將有int *返回類型,你會這樣稱呼:

int *array=fun(); 
printf("%d\n",array[0]); //print the first value in the array 

雖然!請記住,此函數正在返回對本地創建的變量的引用。不保證內存中的值在函數調用內部和後面都是相同的。你可能想要做更多的東西是這樣的:

int *more_fun(){ 
    int *a=malloc(sizeof(int)*3); 
    a[0]=3; 
    a[1]=3; 
    a[2]=4; 
    return a; 
} 

這樣稱呼它:

int *array=more_fun(); 
printf("%d\n",array[0]); //print the first value in the array 

但是當你做,請務必free(array)這樣你就不會泄露任何內存。

4

返回類型不會像其他人所建議的那樣是int*int**。返回類型將是一個指向數組的指針。例如:

// we'll use a typedef so we can keep our sanity: 
typedef int(*int3arrayptr)[3]; 

int3arrayptr fun() 
{ 
    int a[3]={3,3,4}; 
    return &a; 
} 

雖然你可以一個返回指向一個局部變量,則不能使用這樣的指針函數返回後,所以你不能使用的fun()返回值。

+0

除非我弄錯了,否則你不能對返回的指針做任何事情(甚至不會增加或減少它)。 :) – 2010-07-16 14:42:04

+0

@Victor:你是對的;我在這句話的第二部分說「使用」,但是在第一部分中「解除」。我用「使用」來代替「取消引用」來澄清它。謝謝。 – 2010-07-16 14:50:03

1

a是一個局部變量。不要將指針返回給它。

回到正題。這是你如何定義一個指針到數組的大小-3型在C:

int a[3] = { 1, 2, 3 }; 

typedef int (*p_arr_3)[3]; 

p_arr_3 fun() { return &a; } 
0

如果你返回a,返回類型是int *。在這種情況下,我不完全確定&a的含義,而我的便捷參考告訴我可以應用於數組的唯一操作是sizeof,並且我沒有Standard便捷。它可能被標記爲非法,或者可能只是返回值aa表示的唯一東西就是數組,唯一像指向數組的指針是指向其第一個元素的指針。沒有地址的地址。

在C中,很難傳遞數組,因爲數組衰減爲最輕微的挑釁指針。如果你需要傳遞一個實際的數組,最容易將它嵌入到struct中。包含int a[3];struct可作爲常規值傳遞。

我假設你只是舉一個例子,因爲你返回一個局部變量的引用會導致各種不好的事情。在大多數實現中,該內存將用於下一個函數調用的其他事物,這意味着更改一個值會跺腳誰知道什麼,並引用一個會得到誰知道什麼。