前篇内容介绍了简单的 数组与指针 的简单形式. 都是简单的 *p 或者 a[5] 这样的简单形式. 顺便引出了 typedef .
内容相当简单没有深度. 概念也相当简单. 一切皆为数字, 计算机操作的都是数字.
如果上篇没有疑问,下面这段不用再读, 直接跳到 typedef的应用.
回顾一下概念. 变量是什么. 只是一种表示形式而已, 用以表示恰当的存储空间大小的形式.
类型, 只是一种概念,也用来表示空间的大小. 与变量的关系. 变量是表示形式, 类型是空间的大小.
变量都有类型, 指针又是什么. 指针也是一种变量,也有存储空间, 空间的大小就是指针类型所占用的大小. 指针名就是用来表示用以存储"空间地址"的存储空间. 所有指针占用的空间在同一平台下是相等的. 可以用 sizeof(void *) 来获取.
基本的类型有 char, 占用8位, 1字节. short , 占用16位, 2字节, sizeof(char) =1, sizeof(short) =2 . 还有其他一些类型.
typedef 可以用来定义一些类型. 最简单的形式就是给一些基本类型起一些其他的名字. 比如 typedef int abc; 之后, abc 类型和int 类型就是一样的.
数组是一段连续存储空间的表示形式. 比如 char a[5]; 这条语句是一个声明. 表示 5 个sizeof(char) 的连续存储空间. 数组名是 a , 其实, a 也是一个数字, 这个数字就是 所表示的5个空间的首地址. 占用空间大小计算方式为 5*(sizeof(char)); 同理 short b[5]; 中的 b也是一个数字, 对应的是 5个连续 short 的空间首地址. short b[5]占用的存储空间大小为 5*(sizeof(short));
指针 也是占用存储空间的, 占用大小也是固定的. 指针也是一个数字. 存储的是一个 存储空间地址.
typedef的应用
这些在上篇都讲过,这里又啰嗦了一遍. 上篇还讲了一个小魔法. 指针与数组. 下面给出的还是上篇中的例子,我们做些小修改.
#include <stdio.h> typedef char ta[5]; int main(int argc, char *argv[]) { ta a[3]; /*声明数组*/ int i,j; for(i = 0; i < 3; i++) { for (j=0; j < 5;j++ ) { a[i][j] = i*10+j; } } ta *pa; pa=&a[0]; /*这样好理解. 指向数组首地址*/ printf("%d\n", *pa); printf("%d\n", a); printf("%d\n", pa[1][3]); printf("%d\n", *(pa[1]+3)); printf("%d\n", *(*(pa+1)+3)); printf("%d\n", a[0][0]); printf("%d\n", *(*(pa+0)+0)); printf("%d\n", **pa); a[0][0] = 99; printf("%d\n", **pa); }
其中 a 是一个数组, 表示一段连续存储空间. a也是一个数字, 计算机中一切都是数字, a也表示连续存储空间的首地址.
接下来看看 a 这个数组的访问. a 有3个元素, 分别是 a[0] a[1] a[2]. 计算机中,一切都是数字. a 又是 元素的首, 还有其他访问呢形式可用.
a[0] 可表示为 *(a+0) . 意思是, 取 a+0 这个地址对应的内容. 由于 a+0 等于a , 可简单写成 a, 所以 *(a+0) 可简单写成*a;
a[1] 又可表示 *(a+1). 同理 a[2] 可以用 *(a+2) .
这里需要记住的一点, 一切都是数字, 数组表示形式,只是为了让我们好用,好理解, 任何数组都可以用指针的表示形式来表示.
请留意 最后两条语句. 看结果是不是跟想象中的一样. 在这里出现了 **pa ; 试着理解它. 再试着理解*(*pa+1) 和 (*pa)[1] 的关系. 他们是一样的. 用指针表示形式都是一样的.
这里需呀记住的只有一点. 透过表象看本质. 多维数组, 没那么神秘, 数组是用来表示一段连续的存储空间. 多维数组是对多个一维数组的抽象. 最终的本质都是通过指针来访问目标的. 在这里只需要注意的是, 每个目标究竟表示的是什么.
比如 a[1] , 表示的是 是个 ta 类型的内容. ta 类型又表示为一个长度为5的char 数组. 如果将 char 换成 short 类型,结果不会有任何改变. **pa 就是用来表示 *(*pa+0), *pa 的类型是ta, ta又是一个数组, 所以又可以表示为 (*pa)[0],又可以表示为(*(pa+0))[0],或者(pa[0])[0]; 也就是pa[0][0];
二维数组就是这么回事. 用同样的思路去理解3维数组就可以了. 数组,也没什么大不了.
char x[3][5] ,这个声明应该怎么去理解呢? 可以假想成 , 有一个类型, 他的样子类似于 char y[5];
char x[3][5]; 就是有3个像 char y[5] 这样的东西存在. 当然, 的确没有 char y[5]这样的东西. 因为 没有 char y[5] 这样的类型.
所以 char x[3][5] 应该理解成 x[3*5] 也就是 char x[15];
可以将 所有的 char 类型 改变成 short 类型加深理解.
数组可以转换为指针, 指针的形式表示. 反之却不一定成立.
数组与指针就这点关系. 认清本质 会 发现, 也不过如此.
下面将是 字符串与数组的关系.很简单. C语言里没有字符串这个类型, 字符串用 字符数组的概念表示. 不同的是,每个字符串后面都有 '\0' 结束. 字符串的本质就是一个字符数组. 然而,我们运用字符串的时候.更多操作的都是指针. 一个指向字符数组的指针. char (*a)[n]; 类似于这样的指针. 当然, char (*a) [n] 中的 n 是字符串长度下标. 声明的时候可以直接声明成一个字符指针就可以使用了. 留给下一篇再讲.