怎样返回二维数组的指针
怎样返回二维数组的指针
在我编程过程中,有时候需要返回一个二维数组的指针,当然一维数组相信大家都会吧,不过,在此得说明一个名词:栈内存。
栈内存一般主要是应用保存局部变量的,一个函数内部的局部变量(不是动太分配的内存),当从函数返回时,局部变量所占的内存同时也被自动回收,这就是栈内存的一个特性,所以,如果需要从函数返回一个变量的地址,那么只能动态的分配内存。
对于一维数组的问题,不是本文章所讨论的问题,我来所讨论的是怎样返回一个二维数组的地址,在此,首先假设你对指针已经有一定的了解,要不,你会很难看懂下面的问题。指针真是一个好东西,C之真谛我认为也就是指针的所在,同时,C看似很容易入门,其实,入门不那么简单,学习C语言,如果不懂得如何应用指针,那么等于没有学习,如果C中如果没有指针的话,我不敢想像它会变成什么样子,当然,这只是个人的认为,不是大家都认可的。
在学习指针的时候,有一种指针叫做指向数组的指针,应用起来有点像应用二维数组,感觉与二维数组差不多,但是,指针不能与数组混为一谈,在很多C相关的资料上都把指针与数组混在一起,没有明显的区别开来,这对学习者来说是一个很大的误区,让他们认为指针与数组是等价的,如果你手里有这样的一书,说指针就是数组,或者说指针与数组是等价的,那么,请你不要再用这本书,用它将会给你学习指针------C之真谛带来误导,如果把指针与数组给搞混了,那么你还还真没有学好C。
好了,到本文最后也许你就知道指针与数组不能应等价或者就是这两个词来说的。首先我们都明白,一个函数不能返回一个数组,不管是一维的还是二维,但是能返回指针,这一点也可以说明指针与数组的区别吧。这样就好办事了,那么我们可以返回一个这样的指针,该指针指向一个数组,也就指向数组的指针。那么怎么声明函数的原形呢,首我们确定它是一个函数,该函数返回一个指针,该指针指向一个数组,也就是一个返回指向数组指针的函数。好吧,这样一组合起来就可以得到一函数声明如下:
unsigned long (*_my_function(void))[2];
关于些函数的用途我会在后面一一分析。同时,关于声明的优先级规则的问题,请自行参考《C专家编程》这本书,这本书还是不错的,不过得有一定的基础才行。那么我们先把整个例子的源代码先给大家看看,再接着分析源码,这样也许会更好一些,关于本话题目的一个完整的例子源码如下:
#ifndef _TEST_C_
#define _TEST_C_
#include <stdio.h>
#include <stdlib.h>
int _my_add(int,int);
int _my_sub(int,int);
int _my_mul(int,int);
int _my_div(int,int);
int _my_mod(int,int);
unsigned long (*_my_function(void))[2];
int main(void)
{
int number_one;
int number_two;
int number_control;
int result;
unsigned long (*temp_buffer)[2];
temp_buffer = _my_function();
while(1)
{
printf("这是一个简单的计算器,主要有下面的功能!/n");
printf(" 1:加/n 2:减/n 3:乘/n 4:除/n 5:求模/n");
printf("请输入第一操作数 第二操作数 相关运算/n");
scanf("%d %d %d",&number_one,&number_two,&number_control);
if(((number_control == 4) && (!(number_two | 0x0)))/
|| number_control > 5){
printf("input is err/n");
continue;
}
result = ((int (*) (int,int)) /
(*(*(temp_buffer + number_control - 1) + 0)))/
(number_one,number_two);
printf("/n%d %c %d = %d/n/n",number_one,/
*(*(temp_buffer + number_control - 1) + 1),number_two,result);
}
return 0;
}
unsigned long (*_my_function(void))[2]
{
unsigned long (*function_buffer)[2];
function_buffer = (unsigned long(*)[2])malloc(5);
*(*(function_buffer + 0) + 0) = (unsigned long) _my_add;
*(*(function_buffer + 0) + 1) = "+";
*(*(function_buffer + 1) + 0) = (unsigned long) _my_sub;
*(*(function_buffer + 1) + 1) = "-";
*(*(function_buffer + 2) + 0) = (unsigned long) _my_mul;
*(*(function_buffer + 2) + 1) = "*";
*(*(function_buffer + 3) + 0) = (unsigned long) _my_div;
*(*(function_buffer + 3) + 1) = "/";
*(*(function_buffer + 4) + 0) = (unsigned long) _my_mod;
*(*(function_buffer + 4) + 1) = "%";
return function_buffer;
}
int _my_add(int number_one,int number_two)
{
return number_one + number_two;
}
int _my_sub(int number_one,int number_two)
{
return number_one - number_two;
}
int _my_mul(int number_one,int number_two)
{
return number_one * number_two;
}
int _my_div(int number_one,int number_two)
{
return number_one / number_two;
}
int _my_mod(int number_one,int number_two)
{
return number_one % number_two;
}
#endif
上面的例子是本人在网上看到的一道一个公司的笔试题,关于此题我在《函数名之标号地址》一文中写了三个较为简洁的版本,此例子是完全从其中的很三个版本中转变过来的,主要为了说明问题,在实现应用中,此例子会显得有点麻烦,所以,在看此例子的时候,请看文章讨论的要点。
关于题目的要求请去参考我的《函数名之标号地址》一文,在此我就只分析一个函数,unsigned long (*_my_function(void))[2]函数,这个函数才是本文要讨论的问题,首先,从上面的分析中可以知道此函数是一个无形参的函数,该函数的返回值为一个指针数组的指针,所以,我们必须在函数尾返回一个指向数组的指针,并且该指针所指向的地址不是栈内存地址,否则,当函数返回时,此内存空间将被自动回收。
查看该函数就可以知道,在函数首部就声明了一个指向数组的指针,
unsigned long (*function_buffer)[2],并且进行动态内存分配,所以,该内存地址是有效的地址,在函数返回时不会被自动回收。后面的内容不再进行说明。现在来分析一个怎么调用此函数,函数的返回值是一个指向数组的指针,那么我们也可以声明一个指向数组的指针,就可以调用此函数了,在主函数中的unsigned long (*temp_buffer)[2]就是为了调用上述函数而声的了,
temp_buffer = _my_function();实现函数的调用,获得函数返回的地址后,我们就可能像应用二维数组(在此时,该指向数组的指针可以当为二维数组应用,不过还是应用指针的形式更好)应用,相信大家都会应用二维数组吧,例子还是没有把它当着二维数组来用,还是把其当着指针来应用。
好了,我也不知道是不是说清楚了,不过这也就是本人的知识水平的范围之内的事了,如果有不清楚的,你-----我亲爱的读者,有更好的理解,请告诉我,让我也有学习与改正的机会。
舒稳
2010.8.5于长沙理工大学