c語言,c++函數返回一個數組,二維數組

c語言,c++函數返回一個數組,二維數組

與其他高級語言相比,c語言,c++ 最大的不方便之處就是 函數只能返回一個數值。若要返回一個數組,必須用到指針以及動態分配內存。

這是一個坎,就如學吉他時的大橫按一樣,不少人在這個坎上望而卻步。

我前幾年一直看不懂,最近重溫c 與c++的動態內存,發現忽然明白會用了。可能經過這幾年大量的編程,越來越具有程序員思維了吧.

方法之一:返回一個結構體,結構體裏面包括一個數組。

因爲結構體運行效率略慢,這個方法我乾脆不用了。

方法之二:利用指針函數,並結合動態內存。

int *fun()
{
聲明一個動態數組 a;
return a;
}
void main()
{
用指針調用函數 int *p=fun();
釋放該指針 free(p);     (相當於釋放了指針函數裏面的動態數組)
}

舉例:下面程序返回一個一維數組

#include "stdio.h"
#include "stdlib.h"
 
int * Max(int *arr,int n)
{
    int *a=(int *)malloc(2*sizeof(int));
    int maxNum=0,maxIndex,i;
    for (i=0;i<n;i++)
        if (arr[i]>maxNum)
            {maxNum=arr[i];maxIndex=i+1;}
    a[0]=maxNum;a[1]=maxIndex;
    return a;
}
 
void main()
{
	int a[2]={5,2};//a[0]=5,a[1]=2; 
    int *b=Max(a,2);
    int i;
    for(i=0;i<2;i++)
        printf("b[%d]=%d\n",i,b[i]);
 
    free(b);
}

這個程序中的max函數不僅能夠返回一個數組的最大值,還能夠顯示這個最大值在數組中的位置。

下列程序返回一個二維數組,求出一個二維數組各行的最大值以及所在位置。

#include "stdio.h"
#include "stdlib.h"
 
int  **Max(int **arr,int n,int m)
{
    int **data;
	data=(int **)malloc(n*sizeof(int *));
	for (int i=0;i<n;i++)
		data[i]=(int *)malloc(2*sizeof(int));
	for (int i=0;i<n;++i)
	{
		int maxNum=0;
		for (int j=0;j<m;++j)
		{
			//printf("arr[%d][%d]=%d ",i,j,*((int *)arr+m*i+j));
			if (*((int *)arr+m*i+j)>maxNum)
			{
				maxNum=*((int *)arr+m*i+j);
				data[i][0]=maxNum;data[i][1]=j;
			}
		}
		//printf("\n");
	}
    return data;
}
 
void main()
{
	int a[2][3]={5,2,4,6,3,9};
    int **b=Max((int **)a,2,3);
	for (int i=0;i<2;i++)
	{
		printf("the maximum num for row %d is %d\n",i+1,b[i][0]);
		printf("the maximum num for row %d is in %d",i+1,b[i][1]+1);
		printf("\n");
	}
	for(int i=0;i<2;i++)
		free(b[i]);
	free(b);
}

C語言

爲了讓C語言函數返回一個二維數組,有些人這樣定義函數:

int **foo(int rows, int columns)

然後在函數中費勁心機拼出來一個這樣的malloc語句:

int (*result)[columns] = (int (*)[columns])malloc(rows * columns * sizeof(int));

在函數內讀寫這個數組發現很正常,等把數組返回給調用函數後,再讀寫這個數組就crash掉了。
原因其實很簡單,函數返回值類型是int **foo,而實際返回值類型是int (*bar)[columns],它們的區別就是foo[1] - foo[0] = sizeof(int *),而bar[1] - bar[0] = sizeof(int [columns])。把bar賦值給foo以後,訪問foo[1][0]會訪問到啥呢?首先要看foo[1]是個啥,foo[1] = *(foo + 1),那個1雖然看起來是1,但是實際加到foo上的大小實際上是foo指向元素的大小,如果說sizeof(int) = sizeof(int *) = 4的話,也就是foo值增加4,然後對這個地址取值,放到bar中取到了啥呢,實際上取出來的是bar[0][1],所以說,實際上foo[1] = bar[0][1],然而bar[0][1]並不是一個指針或者數組,所以讀foo[1][0]就會crash掉。
正確的做法是這樣的:

int **result = (int **)malloc(rows * sizeof(int *));
for (int i = 0; i < rows; i++)
{
    result[i] = (int *)malloc(columns * sizeof(int));
}

當然你也可以修改函數原型返回類型,但是那樣的話函數看起來就會比較費解一些。當然了,你也可以定義一個結構體,結構體裏面放一個數組,但是這樣做的缺陷就是大小需要固定,沒辦法根據輸入動態產生一個指定大小的結構體。

參考:https://segmentfault.com/q/1010000003481040

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章