当前位置:网站首页>C专家编程 第10章 再论指针 10.3 在锯齿状数组上使用指针
C专家编程 第10章 再论指针 10.3 在锯齿状数组上使用指针
2022-08-10 16:03:00 【weixin_客子光阴】
在锯齿状数组上使用指针
Iliffe向量是一种旧式的编译器编写技巧,最初用于Algol-60。它们原先用于提高数组访问的速度,以及在内存有限的机器中只存储数组的部分数据。在现代的系统中,这两个用途都已毫无必要,但Iliffe向量在另外两个方面仍然具有价值:存储各行长度不一的表以及在一个函数调用中传递一个字符串数组。如果需要存储50个字符串,每个字符串的最大长度可以达到255个字符,可以声明下面的二维数组:
char carrot[50][256];
它声明了50个字符串,其中每一个都保留256字节的空间,即使有些字符串的实际长度只有一两个字节。如果经常这样做,内存的浪费会很大。一种替代方法就是使用字符串指针数组,注意它的所有第二级数组并不需要长度都相同。
如果声明一个字符串指针数组,并根据需要为这些字符串分配内存,将会大大节省系统资源。有些人把它称作“锯齿状数组”,原因是它右端的长度不一。可以通过用字符串指针填充Iliffe向量来创建一个这种类型的数组。字符串指针既可以直接现有的,也可以通过分配内存创建一个现有字符串的副本。
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);
图10-5 创建一个锯齿状数组
只要有可能,尽量不要选择复制整个字符串的方法。如果需要从两个不同的数据结构访问它,复制一个指针比复制整个数组快得多,空间也节省很多。另一个可能影响性能的因素是Iliffe向量可能会使字符串分配于内存中的不同的页面中。这就违反了局部引用的规则(一次读写的数据位于同一个页面上),并导致更加频繁的页面交换,具体如何取决于怎样访问数据以及访问的频度。
数组和指针参数是如何被编译器修改的
“数组名被改写成一个指针参数”的规则并不是递归定义的。数组的数组会被改写为“数组的指针”而不是“指针的指针”。
实参 所匹配的形参
数组的数组 char c[8][10]; char (*)[10]; 数组指针
指针数组 char *c[15]; char **c; 指针的指针
数组的指针(行指针)char (*c)[64]; char (*c)[64]; 不改变
指针的指针 char **c; char **c; 不改变
之所以能在main()函数中看到char **argv这样的参数,是因为argv是个指针数组(即char *argv[])。这个表达式被编译器改写为指向数组第一个元素的指针,也就是指向指针的指针。如果argv参数事实上被声明为一个数组的数组(也就是char argv[10][15]),它将被编译器改写为char (*argv)[15](也就是一个字符数组指针),而不是char **argv。
my_function_1(int fruit[2][3][5]) {;
}
my_function_2(int fruit[][3][5]) {;
}
my_function_3(int (*fruit)[3][5]) {;
}
int apricot[2][3][5];
my_function_1(apricot);
my_function_2(apricot);
my_function_3(apricot);
int (*p)[3][5] = apricot;
my_function_1(p);
my_function_2(p);
my_function_3(p);
int (*q)[2][3][5] = &apricot;
my_function_1(*q);
my_function_2(*q);
my_function_3(*q);
图10-6 所有有效代码的组合
/*
**编程挑战
*/
检验一下
输入图10-6中的C代码,亲手运行一下。
#include <stdio.h>
#include <stdlib.h>
my_function_1(int fruit[2][3][5]);
my_function_2(int fruit[][3][5]);
my_function_3(int (*fruit)[3][5]);
int main( void ){
int apricot[2][3][5];
my_function_1(apricot);
my_function_2(apricot);
my_function_3(apricot);
int (*p)[3][5] = apricot;
my_function_1(p);
my_function_2(p);
my_function_3(p);
int (*q)[2][3][5] = &apricot;
my_function_1(*q);
my_function_2(*q);
my_function_3(*q);
return EXIT_SUCCESS;
}
my_function_1(int fruit[2][3][5]) {
printf( "This is the function form of my_function_1(int fruit[2][3][5])\n" );
}
my_function_2(int fruit[][3][5]) {
printf( "This is the function form of my_function_2(int fruit[][3][5])\n" );
}
my_function_3(int (*fruit)[3][5]) {
printf( "This is the function form of my_function_3(int (*fruit)[2][3][5])\n" );
}
/* 输出:

*/
边栏推荐
猜你喜欢

web安全入门-Kill Chain测试流程

An ABAP tool that can print the browsing history of a user in the system for BSP applications

从抖音到火山引擎——看流媒体技术演进和机会

字符串压缩(三)之短字符串压缩

北海 Kraken:基于 Flutter 构建的高性能 Web 渲染引擎

26、压缩及解压缩命令

秘密共享方案介绍SS

困扰已久的一个微信bug

【服务器数据恢复】raid5崩溃导致lvm信息和VXFS文件系统损坏的数据恢复案例

Taurus.MVC WebAPI 入门开发教程4:控制器方法及参数定义、获取及基础校验属性【Require】。
随机推荐
如何将jpg静图做成gif动图?教你1分钟快速合成gif
WinUI 3 Fundamentals 5小时教学视频
商业智能BI行业分析思维框架:铅酸蓄电池行业(二)
腾讯云TDP-对象存储COS产品新用户福利
App自动化测试框架设计与实现
简述 Mock 接口测试
机器学习天降福音!数据科学家、Kaggle大师发布「ML避坑宝典」
FTXUI基础笔记(botton按钮组件进阶)
openpyxl绘制堆叠图
8月Meetup | “数据调度+分析引擎”解锁企业数字化转型之路
Exchange Online审计和监控
Gif动图制作怎么在线操作?一招教你快速完成gif在线制作
易基因|深度综述:m6A RNA甲基化在大脑发育和疾病中的表观转录调控作用
一文带你了解 HONOR Connect
【每日一题】【leetcode】26. 链表-链表中倒数第k个节点
26、压缩及解压缩命令
铜锁密码库
2025年推出 奥迪透露将推出大型SUV产品
清理空的 Jetpack Compose 应用程序模板
FTXUI基础笔记(hello world)