[英]Function returning a Pointer to an Array
我成功地使用了C
可變長度數組,我現在有以下內容:
#include <stdio.h>
#include <stdlib.h>
int (*foo(size_t row, size_t col))[3];
int main(void){
size_t row, col;
printf("Give the ROW: ");
if ( scanf("%zu",&row) != 1){
printf("Error, scanf ROW\n");
exit(1);
}
printf("Give the COL: ");
if ( scanf("%zu",&col) != 1){
printf("Error, scanf COL\n");
exit(2);
}
int (*arr)[col] = foo(row, col);
for ( size_t i = 0; i < row; i++){
for( size_t j = 0; j < col; j++){
printf("%d ",*(*(arr+i)+j));
}
}
free(arr);
}
int (*foo(size_t row, size_t col))[3]{
int (*arr)[col] = malloc(row * col * sizeof(int));
int l=0;
if (arr == NULL){
printf("Error, malloc\n");
exit(3);
}
for ( size_t i = 0; i < row; i++){
for( size_t j = 0; j < col; j++){
*(*(arr+i)+j) = l;
l++;
}
}
return arr;
}
輸出:
Give the ROW: 2
Give the COL: 5
0 1 2 3 4 5 6 7 8 9
現在這個:
int (*foo(size_t row, size_t col))[3]{ /* code */ }
意味着,如果我理解正確,將foo聲明為具有兩個參數(size_t row,size_t col)的函數,該參數返回指向int數組3的指針。
我並不完全能夠理解這種函數,當我只在運行時知道大小時,使用可變長度數組對我來說更復雜,但我發現這是一件好事。 我只使用C11
標准。
這里有任何方式int (*foo(size_t row, size_t col))[3]
我有這個[3],我不清楚它是如何工作的,如何在運行時使它成為可能(當然只有可能),像int (*foo(size_t row, size_t col))[SIZE]
。
我讀了一些關於C
書,但是沒有關於這種情況的確切解釋,谷歌也沒有幫助,所以我有兩個問題:
1)這是可能的int (*foo(size_t row, size_t col))[SIZE]
,其中SIZE必須是參數? 或者我應該以另一種方式聲明這個功能?
2)這是我在這里嘗試過的正確方法,還是有另一種選擇?
我只是試圖返回一個指向一個數組的指針,該數組在運行時知道大小而不是編譯時間。 malloc
和free
的調用只發生一次,這是一個很好的方法,因為每當調用malloc
,我們的程序會干擾內核分配內存並將頁面標記為可寫。所以這種方法對kernel
較小。 它可以用一個與VLA一起工作的malloc
編寫
編輯:
@ChronoKitsune說我應該使用/ try []
(未指定大小的數組),在這種情況下函數將變成這樣:
int (*foo(size_t row, size_t col))[]{ /* code */ }
這是我應該使用的嗎?
這里有任何方式
int (*foo(size_t row, size_t col))[3]
我有這個[3]
,我不清楚它是如何工作的
類型聲明最容易從里到外讀取。 我會開始簡單,並建立你的榜樣。 如果你寫
int foo[3];
要么
int (foo)[3];
你將foo
聲明為3個int
的數組。 這里的括號提供了一個優先導向分組函數,就像在表達式中一樣,但它們是不必要的,因為在兩種情況下類型的解釋方式都相同。
如果你寫
int (*foo)[3];
你宣稱foo
是一個指向 3 int
數組的指針 。 同樣地,你可以讀到這就是說foo
指向的東西是一個3個int
的數組,隱含foo
是一個指針。 在這種情況下,括號是必要的; 如果沒有它們,你會將foo
聲明為3 int *
的數組。
如果你寫
int (*foo(size_t row, size_t col))[3];
你聲明foo
是一個帶有兩個size_t
類型參數的函數,它的返回值指向一個3 int
的數組。
如何在運行時使其成為可能(當然只有在可能的情況下),例如
int (*foo(size_t row, size_t col))[SIZE]
。
如果SIZE
不是編譯時常量,那么你不能這樣做。 C2011認為
如果標識符被聲明為具有可變修改類型,則它應該沒有鏈接,並且具有塊范圍或函數原型范圍。 [...]
(6.7.6.2/2)
換句話說,因為所有函數都具有文件范圍以及內部或外部鏈接,所以函數返回類型不能是VLA,指向VLA的指針或任何此類型(這些是“可變修改”類型)。
通常,在這種情況下,一個返回指向數組的第一個元素的指針,而不是指向整個數組的指針。 指向地址的方式相同,但類型不同:
int *foo(size_t row, size_t col);
返回類型不包含有關指向數組長度的信息,但如果C允許函數返回可變修改類型,那么無論如何,這將依賴於代碼可以知道任何特定上下文中的變量維度的機制。 換句話說,如果你不知道與函數的返回類型無關的預期數組長度,那么你無論如何也無法使用可變修改的返回類型。
如果確實需要的功能都返回一個指針元件的運行時間確定的數量,並且還元素的數量,則可以返回同時含有結構,也可以通過指針參數返回的一個或兩個的值。
更新 :
如@ChronoKitsune所建議的那樣,也可以聲明你的函數返回一個指向未指定大小的數組的指針。 語法是
int (*bar(size_t row, size_t col))[];
,但你會發現幾乎在所有方面都難以使用返回類型。 例如,聲明可以保存返回值的變量更加棘手和丑陋:
int (*array_ptr)[] = bar(x, y);
並訪問指向數組的元素:
int z = (*array_ptr)[1];
與之形成鮮明對比
int *ptr = foo(x, y);
int w = ptr[2];
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.