[英]Passing 2D arrays in C
我從C中斷了一次,只是又重新回到了C。
如果我想創建一個2D的雙精度數組,我可以通過兩種方式做到這一點:
double** m_array = (double**) malloc(2*sizeof(double*));
double* m_array = (double*) malloc(2*sizeof(double));
要么
double array[2][2];
但是,當我希望傳遞malloc數組而不是傳遞另一個數組時,似乎有兩個約定:
//allowed for passing in malloc'd array, but not for other array
func_m(m_array) //allowed
func_m(array) //disallowed
func_m(double** m_array)
//allowed for passing in either array; required for passing in non-malloc'd array
func(m_array) //allowed
func(array) //allowed
func(double array[][2])
首先,我不需要任何信息,它是指向指針數組的指針。 但是它只能是一個malloc數組。
在第二個中,我需要傳遞double *數組所指向的每個數組的長度。 這似乎很愚蠢。
我想念什么嗎? 提前致謝。
第一個根本不創建二維數組。 它創建一個指針數組,該指針顯然沒有指向。 如果確實將每個指針初始化為一個數組,則該指針仍將是數組的數組,而不是二維數組。
為什么不創建二維數組呢?
double* dynamicArray = malloc(rows * columns * sizeof (double));
要么
double autoArray[rows][columns];
然后您可以使用以下任一功能:
void func(double* array, size_t rows, size_t columns);
為了澄清起見,假設您聲明:
int my_static_array[row][col];
在pmg的答案中,my_static_array與malloc'd數組(稱為my_malloc數組)的類型是什么? my_static_array是內存中連續的row * col * sizeof(int)個字節,並帶有指向其開頭的int *指針。 在計算my_static_array [x] [y]時,編譯器會知道這樣做(因為它們以行優先順序存儲):
*(addr(my_static_array) + [sizeof(int)*col*x] + [sizeof(int)*y])
這就是為什么我需要傳遞C的col值的原因:
(1) func(int my_static_array[][col])
(2) func(int my_static_array[][])
在(1)中,編譯器知道如何為靜態數組正確計算地址。 在(2)中,編譯器沒有足夠的信息。 這就是為什么(1)編譯而(2)不會編譯的原因。
如果是malloc數組,則可以通過:
func(int** my_malloc_array)
由於它是指向一維數組的連續數組的指針,因此編譯器不需要幫助。 my_malloc_array [x] [y]很簡單:
*(*(addr(my_malloc_array)+x)+y)
編譯器不需要其他有關其維數的信息即可進行計算。
那么,這是什么教訓? 二維陣列是不一樣的指針數組至1D陣列。 前者的類型為int(* my_static_array)[row * col]-指向行* col元素數組的指針,后者的類型為int **-指向行指針數組的指針。
您對2D陣列的分配是錯誤的。 通常的2D方法是
double **m_array = malloc(NROWS * sizeof *m_array);
for (i = 0; i < NROWS; i++) {
m_array[i] = malloc(NCOLS * sizeof *m_array[i]);
}
將數組或指針(任何維)傳遞給函數時,必須讓函數知道維:它們未在數組或指針本身內編碼。
一方面,您具有指向某些對象的指針(指向指針(至指針(...))),另一方面,您具有某種類型的數組(數組(屬於數組(...)))。
當您將指針傳遞給函數時,就是這樣。 當您“傳遞數組”時,發生的事情是該數組衰減為指向其第一個元素的指針。 所以
foo(array); // is the same as foo(&(array[0]));
當array
是多維數組時,衰減指針的類型是pointer to array[size] of SOMETHING
(但您不能使用該大小!)。
最簡單的方法是使用簡單的指針編寫函數並傳遞所有維的乘法
double array[3][4][5];
foo(&(array[0][0][0]), 3*4*5);
假設計算機存儲器是一個充滿按順序編號的框的倉庫。 當你做
int matrix[10][3];
您保留30個用於保存矩陣值的框(例如,框131至160)。
現在,假設您要對函數中矩陣中的所有值求和:
int matrix_sum(int matrix[10][3]) { /* ... */ }
但是接收到的所有函數(由標准規定)都是指向矩陣第一個元素的指針:指向3個int
數組的指針。 因此,該函數知道框131、132和133屬於矩陣,但它不知道矩陣實際有多長時間。
使用簡單的typedef:
typedef double Twodouble_t[2];
void func(Twodouble_t *ptr)
{
size_t i, numelements = sizeof*ptr/sizeof**ptr;
puts("first array");
for( i=0; i<numelements; ++i )
printf("\n%f",ptr[0][i]);
}
...
Twodouble_t array[]={ {1., 1.},{2., 2.},{3.,3.} };
func(array);
...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.