精析数组指针和指针数组
程序员文章站
2022-06-23 13:37:25
...
1.什么是指针数组和数组指针?
指针数组:即存放指针的数组。首先它是一个数组,这个数组中的所有元素都是指针类型。
数组指针:即是一个指针,这个指针是指向一个数组的。这个指针变量存放的是一个数组首元素的地址。
2.指针数组和数组指针的表示
2.1 指针数组
char *a[4] = {"ni, "hao", "ma", "firend"};
在指针数组中有两个需要注意的问题,第一个是我们得清楚符号之间结合的优先级问题。C语言规定了"[]"的优先级高于
"*",所以在看到char *a[4]的时候是先找到a[4]这个数组,然后看修饰这个数组的是一个char类型的指针。
第二个需要注意的是求指针数组的大小,因为数组a中存放的都是指针,且每个指针斗都是int类型的指针,大小在32位系统下占四个字节,所以sizeof(a) = sizeof(char *) * 4;答案很明显是16个字节。
2.1 数组指针
定义一个数组指针;
char (*a)[4];
如果指针数组和数组指针这l两个变量名称一样就会是这样:char *pa[4]和char (*pa)[4],原来指针数组和数组指针的形成的根本原因就是运算符的优先级问题。a是一个指针指向一个char [4]的数组,每个数组元素是一个char类型的变量。
既然a是一个指针,存放一个数组的地址,那么在我们定义一个数组时,数组名称就是这个数组的首地址,那么这二者有什么区别和联系呢?
char b[4];,
- 1
- 2
a是一个长度为4的字符数组,b是这个数组的首元素首地址。既然b是地址,a是指向数组的指针,那么能将b赋值给a吗?答案是不行的!因为b是数组首元素首地址,a存放的却是数组首地址,b是char 类型,b+1,b的值会实实在在的加1,而a是char[4]类型的,a+1,a则会加4,虽然数组的首地址和首元素首地址的值相同,但是两者操作不同,所以类型不匹配不能直接赋值。
3.指针数组和数组指针的使用
3.1指针数组在参数传递时的使用
指针数组常用在主函数传参
,在写主函数时,参数有两个,一个确定参数个数,一个这是指针数组用来接收每个参数(字符串)的地址
int main(int argc, char *argv[])
- 1
- 2
此时可以想象内存映像图,主函数的栈区有一个叫argv的数组,这个数组的元素是你输入的参数的地址,指向着只读数据区。
如果是向子函数传参
,这和传递一个普通数组的思想一样,不能传递整个数组过去,如果数组很大,这样内存利用率很低,所以应该传递数组的首地址,用一个指针接收这个地址。因此,指针数组对应着二级指针
void fun(char **pp);//子函数中的形参
fun(char *p[]);//主函数中的实参
- 1
- 2
- 3
3.2指针数组的排序
指针数组的排序非常有趣,因为这个数组中存放的是指针,通过比较指针指向的空间的大小,排序这些空间的地址
。函数实现如下:
void sort(char **pa, int n)//冒泡排序
{
int i, j;
char *tmp = NULL;
for(i = 0; i < n-1; i++){
for(j = 0; j < n-1-i; j++){
if((strcmp(*pa+j), *(pa+j+1)) > 0){
tmp = *(pa + j);
*(pa + j) = *(pa + j + 1);
*(pa + j + 1) = tmp;
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
在函数中定义指针数组,并且打印结果如下:
char *pa[4] = {"abc", "xyz", "opq", "xyz"};
[[email protected] test]# ./test
abc
ijk
opq
xyz
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
数组指针传参时的使用
数组指针既然是一个指针,那么就是用来接收地址,在传参时就接收数组的地址,所以数组指针对应的是二维数组。
void fun(int (*P)[4]);//子函数中的形参,指针数组
a[3][4] = {0};//主函数中定义的二维数组
fun(a);//主函数调用子函数的实参,是二维数组的首元素首地址