本帖最后由 稳稳の幸福 于 2017-4-27 20:15 编辑
二维指针与指针数组对于数组 char *titlesPointerArray[]={ "A Tale of Two Cities", "Wuthering Heights", "Don Quixote", "Odyssey", "Moby-Dick", "Hamlet", "Gulliver's Travels"}这里titlesPointerArray是一个指针数组,titlesPointerArray本身是一个指向数组首元素titlesPointerArray[0]的指针,即titlesPointerArray = &titlesPointerArray[0]。 而titlesPointerArray[0]又是一个指向char的指针,所以可以看到titlesPointerArray是一个指向字符型指针的指针,由此可以看到一个二维指针与指针数组是对应的。 char *titlesPointerArray[]char **titlesPointerArray是等价的。这也是为什么在main函数中char **argv和char *argv[]都是可以的。 二维指针对于处理字符串数组很有好处,动态性能好。可以不用去人为干涉元素数和各字符长度。 二维数组与数组指针对于数组 char titlesDimensionArray[][40]={ "The Art of Computer Programming ", "Python Programming Guide", "Programming Pearl", "Computer Network", "Modern Perl"}这里titlesDimensionArray是一个二维数组。titlesDimensionArray本身是一个指向数组首元素titlesDimensionArray[0]的指针,即titlesDimensionArray = &titlesDimensionArray[0]。 而与指针数组不同的是,titlesDimensionArray[0]不再是指向char的指针,而是一个指向有40个元素数组的指针。同样,titlesDimensionArray[0]代表这40个元素数组的首元素地址,即titlesDimensionArray[0] = &titlesDimensionArray[0][0]。所以可以看到titlesDimensionArray是一个指向数组的指针。由此可以看到一个二维数组与数组指针是对应的。 char titlesDimensionArray[][]char (*titlesDimensionArray)[]是等价的。 这里终于可以看懂二维数组的实质了。虽然最终引用时都使用解引**来获取首个元素内容,但这是不同的。还有就是这种形式跟上面相比要指定内层数组的维数。相对来说更浪费空间,动态性能不好。 动态创建数组鉴于数组与指针相爱相杀,我们还可以使用指针来在堆动态的创建数组。最终使用的时候既可以使用指针,也可以使用数组下标方式。 动态创建的数组由于是在堆上,所以切记要在最后释放内存 一维数组- [size=0.85em]int *pv = (int *)malloc(size * sizeof(int))即动态创建了一个数组pv[size]
- 使用时既可以用pv[0]方式获取内容,也可以使用*(pv+0)来获取内容
使用[size=0.85em]realloc实现变长数组如果不使用C99标准,那么就不能使用变长数组了,我们只能用realloc函数来实现变长数组。 realloc函数的核心功能就是用新区域替换旧的区域,这样如果新区域大于旧区域,便可实现空间的扩大,同时返回区域指针。我们可以根据这个思路来实现变长数组。 二维数据- 既然是二维,为了确定空间大小,我们使用[size=0.85em]rows(外层)和[size=0.85em]columns(内层)的概念来确定整体分配空间大小。总之总大小应该是[size=0.85em]sizeof(rows * columns)
- 使用二维数组定义时,空间是连续分配的,而使用动态分配时,内存可连续,也可能不连续,需要要人为来控制。
- 连续的空间存取速度快,但是空间利用率不高。而动态不连续的内存,空间利用率相对高些。这就是数据结构中静态链表和动态链表的优缺点的本质原因。
- 进行动态分配时,指针维数与数组维数是对应的。
分配可能不连续的内存[size=0.85em]//定义一个二维指针并分配外层(rows)空间int **matrix = (int **)malloc(rows * sizeof(int *));for(i=0; i<rows; ++i) *(matrix+i) = (int *)malloc(columns * sizeof(int));两层均使用动态进行空间分配,内存区域可能连续,也可能不连续。 分配可能连续的内存[size=0.85em]//定义一个二维指针并分配外层(rows)空间int **matrix = (int **)malloc(rows * sizeof(int *));//在第二层分配时,先一次性规划处整个空间,然后再按行切分*matrix = (int *)malloc(rows * columns * sizeof(int));for(i=0; i<rows; ++i) *(matrix+i) = (*matrix)+(columns*i);由于分配内层时使用了整体分配,所以空间是连续的,只需要按行切分即可 函数中数组的传递一维数组的传递在函数参数传递一维数组时,形参可以使用两种方式,以整型为例 void function(int array[], ...),或者 void function(int *a, ...) 这两种方式都是可以的,在函数体内部,既可以使用数组形式,也可以使用指针形式。 - 对于实参,必须是[size=0.85em]指向整型的指针,例:int vector=[]function(vector, ...)二维数组的传递
- 对于二维数组的传递,要确定好形参的使用方式,是使用[size=0.85em]数组指针(二维数组),还是[size=0.85em]指针数组(二维指针)
- 传递二维数组时,一定要对应好形参和实参。
- 如果形参使用[size=0.85em]数组指针(二维数组)。那么实参必须是一个[size=0.85em]指向数组的指针。
- 如果形参使用[size=0.85em]指针数组(二维指针),那么实参必须是一个[size=0.85em]指向指针的指针。
其他- 对多维数组仅可省略最左侧一维的的大小。
- 指针类型与解引操作是不同的
- 二维以上的数组或指针相对难理解,尽量少使用
- 变长数组的支持和利用复合字面量(composite literal)实现不规则数组和指针是C99新增特性,目前不考虑使用
- 数组和指针还是有区别的。数据名是右值(常量),而使用指针定义的数据,指针是左值(变量)
- 求一维数组的大小可以使用index = sizeof(vector)/sizeof(int)
|