[3] 数组和指针的前世今生 - 指针篇

指向字符串的一维指针数组,char* pea[10]

  • 上述声明,pea是一个具有10个元素的数组,每个元素的类型是一个指向字符(或者字符串)的指针,从声明中无法得知是单个字符还是字符串
  • 用于实现多维数组的指针数组有很多名字,如“Iliffe向量”、“display”或“dope向量”
  • 这种数组必须用指向为字符串而分配的内存的指针进行初始化,可以在编译时用一个常量初始值,也可以在运行时动态malloc初始化,for循环为每一个元素malloc可以,直接为整个数组malloc也可以,只不过后者还需要使用一个循环来用指针指向这块内存的各个区域。前者的好处是可以逐个释放内存,后者的优点是内存是连续的

squash[i][j]

  • 当你看到squash[i][j]时,不知道squash是怎样声明的,和函数内部不知道传入的变量是数组还是指针一样,都是因为左值的数组名被编译器当作指针
int squash[23][12];//数组
int *squash[23];//Iliffe向量
int **squash;//2级指针
int (*squash)[12];//指针,指向int[12]
  • 尽管都写作squash[i][j],但是在不同的情况下访问的实际类型是不同的。
  • quash[i][j]被编译器翻译为*(*(quash+i)+j),访问方式很不相同,如下:
    这里写图片描述
    这里写图片描述

Iliffe向量,在锯齿状数组上使用指针

  • char carrot[50][256];虽然不是每次都会用到256个字符,但是最大长度是256,所以很大一部分空间被浪费了
  • char* carrot[50];每个数组元素指向的长度不一,节省了内存
  • 初始化锯齿状数组有两种方式,共享字符串,或者拷贝字符串
char *turnip[UMPTEEN];
char my_string[]="your message here";
//共享
turnip[i] = &my_string[0];
//拷贝
turnip[j] = malloc(strlen(my_string)+1);
strcpy(turnip[j],my_string);
  • 尽量不要选择拷贝整个字符串的方法,缺点是空间耗费,而且可能使得字符串分配在内存的不同页面中,影响性能

数组和指针参数的匹配

数组名被改写成指针的规则不是递归定义的,数组的数组会被改写成数组的指针而不是指针的指针

实参所匹配的形式参数
数组的数组char c[8][10];char(*)[10]数组指针
指针数组char *C[15];char**c;指针的指针
数组指针char(*c)[64];char(*c)[64];不改变
指针的指针char **c;char**c;不改变

因此main函数的入参argv**和argv*[]都是合法的

下面列举了所有有效的代码组合:

void my_func1(int fruit[2][3][5]);
void my_func2(int fruit[][3][5]);
void my_func3(int (*fruit)[3][5]);
int apricot[2][3][5];
my_func1(apricot);
my_func2(apricot);
my_func3(apricot);
int (*p)[3][5] = apricot;
my_func1(p);
my_func2(p);
my_func3(p);
int (*q)[2][3][5] = &apriot;
my_func1(*q);
my_func2(*q);
my_func3(*q);
  • 3个函数都接受同样类型的参数,就是一个[2][3][5]int型的三维数组或一个指向[3][5]int型二维数组的指针
  • 3个变量apricot,p,*q都匹配所有3个函数的参数声明

Reference

C专家编程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值