C专家编程(十)

来源:互联网 发布:域名注册扫描工具 编辑:程序博客网 时间:2024/05/01 19:21
第十章 再论指针
1、多维数组内存布局
p[i][j]=*(*(p+i)+j);

2、指针数组
一个一维指针数组,每个指针指向一个字符串取得类似二维数组的效果
char *p[20]; 必须用指向字符串而分配的内存的指针初始化
for(int i=0;i<20;i++)
    p[i]=malloc(6);
1)数组的数组
char a[4][6]的定义表示a是一个包含4个元素的数组,每个元素是一个char类型的数组(长度为6)。
查找到第4个数组的第i个元素(前进i*6个字节),然后找到数组中的第j个元素。
2)字符串指针数组
char *p[4]的定义表示p是一个包含4个元素的数组,每个元素是一个指向char的指针。
查找到第i个元素(每个元素均为指针),取出指针的值,加上偏移量j,以此为地址,取出地址的内容。

3、数组和指针参数
                                  实参                          匹配的形参
数组的数组             char c[8][10]                  char (*c)[10]      数组指针
指针数组                char *c[10]                    char **c             指针的指针
数组指针                char (*c)[10]                  char (*c)[10]      不变
指针的指针             char **c                        char **c             不变
 
4、向函数传递一维数组
形参被改写为指向数组第一个元素的指针,需要约定数组长度
1)增加一个额外的参数,表示元素的数目
2)赋予数组最后一个元素一个特殊值

5、使用指针向函数传递一个多维数组
没有办法向函数传递一个普通的多维数组,必须提供除了最左边一维以外的所有维的长度,把实参限制为除最左边一维都必须与形参匹配的数组
1)方法一
my_function(int my_array[10][20]);
只能处理10行20列的int型数组
2)方法二
my_function(int my_array[][20]);
my_function(int (*my_array)[20]);
每一行必须是20个int整数的长度
3)方法三
my_function(char** my_array);
必须是指针数组,而且必须是指向字符串的指针数组。因为字符串和指针都有一个显式的越界值(分别为NUL和NULL)。
4)方法四

6、使用指针从函数返回一个数组
1)声明:
int (*paf())[20];
paf是一个函数,返回一个指向包含20个int元素的数组的指针。
2)定义:
int (*paf())[20]
{
    int (*pear)[20];
    pear=calloc(20,sizeof(int));
    if(!pear)
          longjmp(error,1);
    return pear;
}
3)调用:
int (*result)[20];   //指向含有20个int元素的数组的指针
result=paf();
(*result)[3]=12;
注:使用malloc申请的是堆空间,不由函数机制控制,可以由程序的任意部分调用,需要手动使用free释放。
       可以跨函数引用,不需要占据静态存储区。
也可以使用结构体实现!
不能从函数返回一个指向函数的局部变量的指针!

7、使用指针创建和使用动态数组
使用malloc()库函数分配得到一个指向内存的指针,然后可以像引用数组一样引用这块内存
实现表自动增长,采用库函数realloc(),可以对内存大小重新分配,而不会丢失原有内容。
当需要增长时:
1)对表检查是否已满
2)如果已满,使用realloc()扩展表的长度,并进行检查,确保扩展成功
3)在表中增加需要的内容
问题:
1)表增大,可能是系统速度变慢
2)重新分配操作,可能移动一个不同的位置,导致原来的地址不再有效。所以最好使用下标而不是元素的地址
3)增加和删除操作必须通过函数进行,导致操作比仅仅使用下标多得多
4)表减小时,应该缩小表并释放多余的内存
5)多线程中,锁住表,防止重新分配时,有其他线程访问表