另类解读C语言数组的特性
2011-11-24 00:12
246 查看
数组的本质其实就是把多个相同数据类型的变量捆绑在一起使用而已。例如int a[10],其实质就是把10个整型变量按照地址从低到高的顺序依次分配在一段连续的40个字节的内存空间上。
1、一维数组
一维数组举例,如清单1:
第5行定义了一个一维的整型数组a,共有5个元素,并被初始化为整数1、2、3、4和5。注意,这里所说的“整型数组”的“整型”其实指的是数组中单个元素的数据类型,数组本身的数据类型是一种组合型的数据类型,并没有相应的关键字来表示。
回顾一下指针变量的定义,如第7行定义了一个指针变量p,定义中的关键字int指的是指针变量p将只能匹配整型数据的首地址。而数组名a代表的是其第一个元素a[0]的首地址(数组名代表着数组的首地址的说法欠准确),也就是说把a(等价于&a[0])赋给指针变量p(这时候就可以说p指向了a[0]),它们的数据类型是相匹配的,因为a[0]是整型变量,而p只匹配整型数据的首地址。
虽然&a与&a[0]的值相同,但它们的数据类型并不相同,a[0]的数据类型为int,而整个数组的数据类型为int [5](是一种组合数据类型,由int和[5]共同决定),所以与&a匹配的指针变量只能是类似于第10行的pa。
也就是说,数组单个元素的数据类型和指针变量将要指向的数据类型是一致的。
例子输出结果:
p+1为第二个元素a[1]的首地址,而pa+1的值是整个数组后面的那个地址。
2、多维数组
在C语言当中,没有所谓的多维数组,只有数组的数组。
多维数组举例,如清单2:
第5行,a是一个三维数组,共有两个元素,每个元素的数据类型为int [3][5]。
a[0]和a[1]分别都是二维数组,每个数组共有三个元素,每个元素的数据类型为int [5]。
a[0][0]、a[0][1]、a[0][2]、a[1][0]、a[1][1]和a[1][2]分别都是一维数组,每个数组共有五个元素,每个元素的数据类型为int。
例子输出结果:
结合下面的图形好好地体会为什么输出这样的结果:
3、指针数组和数组指针
指针数组,是一个数组,只不过所有元素都是指针变量。
数组指针,是一个指针变量,只不过它将指向的数据类型为某种形式的数组,如清单1中的pa,清单2中的p0、p1和p2。
指针数组的例子,如清单3:
例子输出结果:
第8行定义了一个指针数组,共有两个元素,每个元素都是将要指向整型数据的指针变量。
p[0]的值就是数组a的首地址,所以p[0][1]就等价于a[1]。
p[1]的值就是数组b的首地址,然后加2获得数组b第3个元素的首地址,最后通过间接运算符(*)取出第3个元素的值。
4、数组在函数形参中的应用
数组在函数形参中等价于一个相应的指针变量。如清单4:
例子输出结果:
整个例子的含义是p =&b[0],而数组指针a = p。
1、一维数组
一维数组举例,如清单1:
#include <stdio.h> int main(void) { int a[5] = {1, 2, 3, 4, 5}; int *p = a; //等价于int *p = &a[0]; //绝不等价于int *p = &a; int (*pa)[5] = &a; printf("a = %p, p+1 = %p, pa+1 = %p\n", a, p+1, pa+1); return 0; }
第5行定义了一个一维的整型数组a,共有5个元素,并被初始化为整数1、2、3、4和5。注意,这里所说的“整型数组”的“整型”其实指的是数组中单个元素的数据类型,数组本身的数据类型是一种组合型的数据类型,并没有相应的关键字来表示。
回顾一下指针变量的定义,如第7行定义了一个指针变量p,定义中的关键字int指的是指针变量p将只能匹配整型数据的首地址。而数组名a代表的是其第一个元素a[0]的首地址(数组名代表着数组的首地址的说法欠准确),也就是说把a(等价于&a[0])赋给指针变量p(这时候就可以说p指向了a[0]),它们的数据类型是相匹配的,因为a[0]是整型变量,而p只匹配整型数据的首地址。
虽然&a与&a[0]的值相同,但它们的数据类型并不相同,a[0]的数据类型为int,而整个数组的数据类型为int [5](是一种组合数据类型,由int和[5]共同决定),所以与&a匹配的指针变量只能是类似于第10行的pa。
也就是说,数组单个元素的数据类型和指针变量将要指向的数据类型是一致的。
例子输出结果:
a = 0xbfd2d1b4, p+1 = 0xbfd2d1b8, pa+1 = 0xbfd2d1c8
p+1为第二个元素a[1]的首地址,而pa+1的值是整个数组后面的那个地址。
2、多维数组
在C语言当中,没有所谓的多维数组,只有数组的数组。
多维数组举例,如清单2:
#include <stdio.h> int main(void) { int a[2][3][5] = { { {1, 2, 3, 4, 5 }, {6, 7, 8, 9, 10}, {11, 12, 13, 14, 15} }, { {16, 17, 18, 19, 20}, {21, 22, 23, 24, 25}, {26, 27, 28, 29, 30} } }; int (*p0)[2][3][5] = &a; printf("&a = %p, p0 = %p, p0+1 = %p\n", &a, p0, p0+1); int (*p1)[3][5] = a; //等价于int (*p1)[3][5] = &a[0]; printf("p1 = %p, p1+1 = %p, ***(p1+1) = %d\n", p1, p1+1, ***(p1+1)); int (*p2)[5] = a[0]; //等价于int (*p2)[5] = &a[0][0]; printf("p2 = %p, p2+4 = %p, **(p2+4) = %d\n", p2, p2+4, **(p2+4)); int *p3 = a[1][2]; //等价于int *p3 = &a[1][2][0]; printf("p3 = %p, p3+2 = %p, *(p3+2) = %d\n", p3, p3+2, *(p3+2)); printf("a[1][0][0] = %d, a[1][1][0] = %d, a[1][2][2] = %d\n", a[1][0][0], a[1][1][0], a[1][2][2]); return 0; }
第5行,a是一个三维数组,共有两个元素,每个元素的数据类型为int [3][5]。
a[0]和a[1]分别都是二维数组,每个数组共有三个元素,每个元素的数据类型为int [5]。
a[0][0]、a[0][1]、a[0][2]、a[1][0]、a[1][1]和a[1][2]分别都是一维数组,每个数组共有五个元素,每个元素的数据类型为int。
例子输出结果:
&a = 0xbfdb1e88, p0 = 0xbfdb1e88, p0+1 = 0xbfdb1f00 p1 = 0xbfdb1e88, p1+1 = 0xbfdb1ec4, ***(p1+1) = 16 p2 = 0xbfdb1e88, p2+4 = 0xbfdb1ed8, **(p2+4) = 21 p3 = 0xbfdb1eec, p3+2 = 0xbfdb1ef4, *(p3+2) = 28 a[1][0][0] = 16, a[1][1][0] = 21, a[1][2][2] = 28
结合下面的图形好好地体会为什么输出这样的结果:
3、指针数组和数组指针
指针数组,是一个数组,只不过所有元素都是指针变量。
数组指针,是一个指针变量,只不过它将指向的数据类型为某种形式的数组,如清单1中的pa,清单2中的p0、p1和p2。
指针数组的例子,如清单3:
#include <stdio.h> int main(void) { int a[3] = {1, 2, 3}; int b[3] = {4, 5, 6}; int *p[2] = {a, b}; printf("p[0][1] = %d, *(p[1]+2) = %d\n", p[0][1], *(p[1]+2)); return 0; }
例子输出结果:
p[0][1] = 2, *(p[1]+2) = 6
第8行定义了一个指针数组,共有两个元素,每个元素都是将要指向整型数据的指针变量。
p[0]的值就是数组a的首地址,所以p[0][1]就等价于a[1]。
p[1]的值就是数组b的首地址,然后加2获得数组b第3个元素的首地址,最后通过间接运算符(*)取出第3个元素的值。
4、数组在函数形参中的应用
数组在函数形参中等价于一个相应的指针变量。如清单4:
#include <stdio.h> void func(int a[2][3]) //这里的int a[2][3]等价于int (*a)[3] { int i, j; for (i = 0; i < 2; i++) for (j = 0; j < 3; j++) printf("a[%d][%d] = %d\n", i, j, a[i][j]); } int main(void) { int b[2][3] = { {1, 2, 3}, {4, 5, 6} }; int (*p)[3] = b; func(p); return 0; }
例子输出结果:
a[0][0] = 1 a[0][1] = 2 a[0][2] = 3 a[1][0] = 4 a[1][1] = 5 a[1][2] = 6
整个例子的含义是p =&b[0],而数组指针a = p。
相关文章推荐
- 另类解读C语言数组的特性
- 另类解读C语言数组的特性
- 深入理解C语言特性-指针 数组 声明
- C语言中可能你不知道的特性(数组下标的来历)
- 读帮助文档发现Delphi2009的新特性,象C语言一样用数组方式使用指针.
- 解读C语言中函数指针数组构成的复杂定义
- C语言特殊语法(五)另类数组
- 参数声明中的静态数组索引:一个不错且鲜为人知的C语言特性
- C99 c语言特性 数组可以这样初使化
- C语言数组特性-取下标运算中的交换律----i[a] == a[i]
- 参数声明中的静态数组索引:一个不错且鲜为人知的C语言特性
- C语言特性(指针与数组)
- C语言特性(指针数组和指向指针变量的指针)
- 全面解读Objective-C语言及Cocoa特性——《Objective-C基础教程》
- 全面解读Objective-C语言及Cocoa特性——《Objective-C基础教程》
- C03_C语言-数组
- c#跟objective-c语言特性的对比
- C语言之_指针数组、结构体、动态内存分配
- 用c语言指针实现给整形数组冒泡排序
- c语言:将数组A中的内容和数组B中的内容进行交换。(数组一样大)