[英]Pointer to a 2-D array
拜托,我是C編程的新手,請幫我這個忙。以下代碼有錯誤嗎? 基本上,我們如何使用指向二維數組的指針...
#include<stdio.h>
#include<stdlib.h>
int* max5(int** p,int r,int c)
{
/* have to design a function which takes as argument pointer to a 2-D array and returns a pointer to an array which contains the 5 highest entries*/
}
int main()
{
int rows,coloumns;
printf("Enter the number of rows and coloumns separated by a space\n");
scanf("%d %d",&rows,&coloumns);
int **ptr;
ptr=(int**)malloc(sizeof(int*)*rows);
int i,j;
for(i=0;i<rows;i++)
{
for(j=0;j<coloumns;j++)
{
scanf("%d",*(ptr+i)+j);
printf("%d\n",*(*(ptr+i)+j));
}
}
free(ptr);
return 0;
}
在C語言中,二維數組只是具有不同索引的常規數組。 因此,您有兩個選擇:
array[I*n+j]
您可以按照相關文章中所示的方式實現第二個目標: 在C中分配矩陣 。
動態分配2D數組可以通過幾種方式完成。
假設您有一個支持可變長度數組的C99編譯器或C2011編譯器,這很簡單:
int rows, columns;
...
scanf("%d %d",&rows,&columns);
int array[rows][columns];
array
是可變長度數組(VLA),這意味着其尺寸是在運行時確定的。 要將其傳遞給另一個函數,原型就是
int *max5( int rows, int columns, int arr[rows][columns] ) { ... }
也可以寫成
int *max5( int rows, int columns, int (*arr)[columns] ) { ... }
我將在下面介紹第二種形式。 請注意,必須先聲明rows
和columns
然后才能在VLA聲明中使用它們。
您將其稱為
int *maxarr = max5( rows, columns, array );
這種方法的優點是:a)很容易,並且b) array
的內存是連續分配的(即,作為一個連續的內存塊),並在退出其封閉范圍時立即釋放; 無需手動free
它。 這種方法的缺點是rows
和columns
不能任意大,您不能使用常規的初始化程序語法來初始化數組(即,您不能編寫int array[rows][columns] = { ... };
),並且您不能在文件范圍內定義VLA(即,作為全局變量)。 還存在一個問題,即VLA支持始終有些參差不齊,並且2011年標准現在使它們成為可選項,因此不能保證將在所有地方都支持它們。
如果rows
或columns
很大,或者出於某些其他原因要從堆中分配此內存,則稍微復雜一點:
int rows, columns;
...
scanf("%d %d", rows, columns);
int (*array)[columns] = malloc( sizeof *array * rows );
在這個版本中, array
是一個指向的N元件陣列int
(其中N == columns
),並且我們malloc
的空間來容納M個這種陣列(其中,M == rows
)。 同樣,這利用了VLA語法,但是我們不是從堆棧幀分配內存,而是從堆分配內存。 像第一種方法一樣,內存是連續分配的。 您將像其他數組一樣索引其中:
array[i][j] = x;
完成數組操作后,您可以將其釋放為
free( array );
max5
的原型是
int *max5( int rows, int columns, int (*arr)[columns] ) { ... }
看起來熟悉? 那是我們先前通過2D VLA時使用的第二個版本。
除非它是sizeof
或一元&
運算符的操作數,或者是用於在聲明中初始化另一個數組的字符串文字,否則類型為“ T
N元素數組”的表達式將轉換為類型為“”的表達式。指向T
“的指針,表達式的值將是數組中第一個元素的地址。
在我們將array
聲明為2D VLA的第一種情況下,當您調用
int *maxarr = max5( rows, columns, array );
表達array
從型轉換“ rows
的-元素陣列columns
-元素的數組int
”到“指針columns
-元素的陣列int
”,所以什么max5
接收是一個指針值,而不是陣列。 碰巧在函數參數聲明的上下文中, T a[N]
和T a[]
都被解釋為T *a
; IOW,三個都聲明a
作為指向T
的指針。
因此,兩者
int *max5( int rows, int columns, int arr[rows][columns] ) { ... }
和
int *max5( int rows, int columns, int (*arr)[columns] ) { ... }
將arr
聲明為指向數組而不是2D數組的指針。 同樣,兩者都返回一個簡單的int *
,而不是一個int
數組。 這樣做的原因是簡單的; 如果您使用返回子數組
return arr[i];
表達arr[i]
將具有類型“ columns
-元素的陣列int
”; 根據上述規則,該表達式將被轉換為int *
類型。 C不允許您將數組對象返回為array ,數組表達式也不能成為賦值的目標。
現在,如果您使用的是C89編譯器或不支持VLA的C2011編譯器,該怎么辦? 在這種情況下,您需要以零散的方式分配內存,如下所示:
int rows, columns;
int **array;
...
scanf("%d %d", rows, columns);
array = malloc( sizeof *array * rows );
if ( array )
{
int i;
for ( i = 0; i < rows; i++ )
{
array[i] = malloc( sizeof *array[i] * columns );
}
}
現在,您的max5
原型為
int *max5( int rows, int columns, int **arr );
您不再處理數組或指向數組的指針; 您正在處理雙指針,這與指向2D數組的指針不同。 您仍然可以對其進行下標, 就好像它是2D數組一樣
arr[i][j] = x;
但它本身不是數組對象。
要意識到的最重要的事情是,不能保證內存是連續的; 行可能不會在內存中相鄰,所以你不想嘗試使用指針走行,像這樣:
int (*p)[columns] = arr;
while ( some_condition )
p++; // sets p to point to the next row
對於零散分配的數組,這種算法將不起作用。
另外,由於內存是零散分配的,因此需要零散地釋放它:
for ( i = 0; i < rows; i++ )
free(array[i]);
free( array );
希望能有所幫助。
此代碼可解決您的問題:
#include<stdio.h>
#include<stdlib.h>
int* max5(int** p,int r,int c)
{
/* have to design a function which takes as argument pointer to a 2-D array and returns a pointer to an array which contains the 5 highest entries*/
}
int main()
{
int rows,coloumns;
printf("Enter the number of rows and coloumns separated by a space\n");
scanf("%d %d",&rows,&coloumns);
int **ptr;
int i,j;
ptr=(int**)malloc(sizeof(int*)*rows);
for(j=0;j<coloumns;j++)
{
*(ptr+j) = (int *)malloc(sizeof(int)*coloumns);
}
for(i=0;i<rows;i++)
{
for(j=0;j<coloumns;j++)
{
scanf("%d",*(ptr+i)+j);
//*(*(ptr+j)+i) = i+j;
printf("%d\n",*(*(ptr+i)+j));
}
}
free(ptr);
return 0;
}
實際上,您忘記為列分配內存!
您可以通過正確定義類型在C中分配2D數組:
int (*ptr)[coloumns] = calloc(sizeof(int) , rows * coloumns);
然后,您可以通過ptr[i][j]
。 如果您的數組確實需要保留在分配它的范圍之外並且很小,那么您也可以在堆棧上分配它
int ptr[rows][coloumns];
memset(ptr, 0, sizeof(ptr));
您試圖分配的是一個指針數組int (*)[coloumns]
與int **
類型不同,盡管它們都可以通過使用索引運算符[i][j]
進行尋址。 后者的數據結構要復雜得多,並且容易出錯。 除非您需要可變的行大小,否則我建議您不要這樣做。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.