当前位置:网站首页>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" );
}

/* 输出:

*/ 

原网站

版权声明
本文为[weixin_客子光阴]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_40186813/article/details/126091970