千万不要忘了,当你把一个手指指向别人的时候,你手上的另外还有三个手指指向了你自己·····
指针数组
数组下标的规则告诉我们如何计算左pea[i][j],首先找到pea[i]的位置,然后根据偏移量[j]取得字符。因此,pea[i][j]将被编译器解析为*(*(pea+i)+j)
- 指针数组就是一个Iliffe向量。
可以通过声明一个一维指针数组,其中每个指针指向一个字符串来取得类似二维字符数组的效果。
这种形式的声明如下。
char *pea[4]
这种数组必须用指向为字符串而分配的内存的指针进行初始化,可以在编译时用一个常量初始值,也可以在运行时用下面这样的代码进行初始化:
for(j = 0;j<=4;j++) {pea[j] = malloc(6);}
另一种方法是一次性地用malloc分配整个x*y
个数据的数组:
mallloc(row_size * column * sizeof(char))
然后,使用一个循环,用指针指向这块内存的各个地址的各个区域。整个数组保证能够存储在连续的内存中,即安C用于分配静态数组的次序。它减少了malloc的维护性开销,但缺点是当处理完了一个字符串时无法单独将其释放。
在锯齿状数组上使用指针
如果需要存储50个字符串,每个字符串的最大长度可以达到255个字符,可以声明下面的二维数组:
char carrot[50][255];
它声明了50个字符串,其中每个都保留256字节的空间,即使有些字符串的实际长度只到一两个字节。如果经常这样做,内存浪费大。一种代替方法就是使用字符串指针数组,他的所有第二级数组并不需要长度都相同。
如果声明一个字符串指针数组,并根据需要为这些字符串分配内存,将会大大节省系统资源。有些人把它称作锯齿状数组是因为它右端的长度不一。
char * turnip[UMPTEEN];
char my_string[]="your message here";
/*共享字符串*/
turnip[i] = &my_string;
/*拷贝字符串*/
turnip[j] = mallloc(strlen(my_string)+1);
strcpy(turnip[j],my_string);
关于多维数组
- 在C语言中,没有办法向函数传递一个普通的多维数组。
这是因为我们需要知道每一维的长度,以便为地址运算提供正确的单位长度。在C语言中,我们没有办法在实参和形参之间交流这种数据(它在每次调用时会改变)。因此,你必须提供除了最左边以外的所有维的长度。这样就把实参限制为最左边一维外所有维都必须与形参匹配的数组。
invert_in_place(int a[][3][5]);
/*用下面两种方法调用可以*/
int b[10][3][5];invert_in_place(b);
int b[999][3][5];invert_in_place(b);
/*下面两种调用方法错误*/
int fails1[10][5][5];invert_in_place(fails1);//无法通过编译
int fails2[10][5][5];invert_in_place(fails2);//无法通过编译
使用指针从函数返回一个数组
严格地说,无法直接从函数返回一个数组。但是,可以让函数返回一个指向任何数据结构的指针,当然也可以是一个指针。
int (*paf())[20]
{
int (*pear)[20];//声明一个指向包含20个int元素的数组的指针
pear = calloc(20,sizeof(int));// 在内存的动态存储区中分配20个长度为sizeof(int)的连续空间,函数返回一个指向分配起始地址的指针
if (!pear) {
longjmp(error,1);
}
return pear;
}
//调用
int (*result)[20];//声明一个指向包含20个int元素的数组的指针
result = paf();//调用函数
(*result)[3] = 12;//访问结果数组
注意,不能从函数中返回一个指向函数的局部变量的指针!