娓娓道来c指针 (5)c数组本质

(5)c数组本质

c中的数组是一种聚合类型,把同种类型的元素按顺序存储,即是数组。c中数组类型的特点在于:它是嵌套定义的。

看下一个二维数组int array[2][3]={{1,2,3},{4,5,6}};的内存存储形式:

c中的数组是嵌套定义的:二维数组的元素是一维数组,三维数组的元素是二维数组……

像array[2][3]这样的二维数组,是由两个一维数组组成的:array[0]、array[1],这两个一维数组的规模都是array的第二个下标3。同时,array[0]、array[1]就是两个一维数组名。由于元素都是顺序存储的,故可以通过以下的方式挨个访问array中元素:

int main(void)
{
	int array[2][3] = {
		{ 1, 2, 3 },
		{ 4, 5, 6 }
	};
	//让p指向数组首元素
	int *p = &array[0][0];
	while (p < &array[1][3])
	{
		printf("%4d", *p);
		p++;
	}
	printf("\n\n");
	return 0;
}

运行

这种访问方式能够成功,关键就在于c中的多维数组本质是数组的数组,并且元素顺序存储。

在代码中出现了&array[1][3],是不是越界了呢?理论上array[1][2]是array的最后一个元素,array[1][3]正好是其下一个,这里我们取其地址,而不是访问元素,这是可以的。

下面来探讨一下这三个数组名:array、array[0]和array[1]是何种类型的指针。

首先,在(3)数组和指针中,我们提到过,对于数组int array[N];(N是一常量)。数组名array是一指向数组首元素的常量指针(也就是说,不可再指向别的存储单元),而&array是一指向整个数组的指针。这里以此类推:

  1. array[0]是指向array[0][0]的指针,类型是int *。&array[0]是指向数组的指针,类型是int(*)[3]。
  2. array[1]和array[0]类型相同,&array[1]和&array[0]的类型相同。当然,只是类型相同,值不同。
  3. array应是指向array[0]的指针,而array[0]是一个一维数组int [3],故array是一个指向一维数组的指针,类型是int(*)[3]。&array应是指向整个二维数组的指针,类型是int(*)[2][3]。

做实验验证:

int main(void)
{
	int array[2][3] = {
		{1, 2, 3},
		{4, 5, 6}
	};
	int *pa = array[0];
	int (*pb)[3] = &array[0];
	int (*pc)[3] = array;
	int (*pd)[2][3] = &array;
	return 0;
}

编译下,无任何警告,我们的猜想正确。以上两个实验可以充分说明c数组的本质:数组的数组

小测一下;

三维数组 int array[2][3][4]; array的类型?&array的类型?array[0]的类型?array[0][0]的类型?(答案在最后,先想想,再看答案。)

另一种测试,使用指针运算来验证

int main(void)
{
	int array[2][3] = {
		{1, 2, 3},
		{4, 5, 6}
	};
	int *pa = array[0];
	int (*pb)[3] = &array[0];
	int (*pc)[3] = array;
	int (*pd)[2][3] = &array;
	printf("array...%p\n", array);
	printf(" pa+1...%p\n", pa + 1);
	printf(" pb+1...%p\n", pb + 1);
	printf(" pc+1...%p\n", pc + 1);
	printf(" pd+1...%p\n", pd + 1);
	return 0;
}

运行

计算后四者和array的差值,结论即可得到。

总结

c数组的本质是:数组的数组。至于数组名 array 和 &array 的指针类型问题,只需记忆两点,其它可推理。这两点是:

  1. array指向数组首元素,弄清楚了元素类型是什么,指针类型自然就推出来了。
  2. &array被规定为指向整个数组,它的类型更简单。

测试答案

array的类型是int(*)[3][4];&array的类型是int(*)[2][3][4];array[0]的类型是int(*)[4];array[0][0]的类型是int*。

专栏目录:C指针

娓娓道来c指针 (5)c数组本质

时间: 2024-07-29 20:24:46

娓娓道来c指针 (5)c数组本质的相关文章

娓娓道来c指针 (3)指针和数组

(3)指针和数组 在c中指针和数组似乎有着千丝万缕的关系.其实它们不是一回事:指针是指针,数组是数组,两者不相同. 说它们有关系,不过是因为常见这样的代码: int main() { int array[] = {1,2,3,4,5}; int n = sizeof(array) / sizeof(int); int *p = array; int i; for (i = 0; i < n; i++) printf("p[%d]...%d\n", i, p[i]); system

娓娓道来c指针 (0)c语言的梦魇:c指针

(0)c语言的梦魇:c指针 序 c语言中有一个重点:c指针.它也是一个难点.当然,这是一句废话:重点往往也是难点.在c标准中,对指针的定义是这种: 指针的类型是derived from其他类型,也就是说指针的类型是由它指向的类型决定的: 指针是一种reference类型,即引用类型: c指针似乎非常难理解,以至于有人指出:掌握了c指针,就掌握了c语言的精髓.本系列就来聊聊c指针,要想弄懂c指针.光就指针本身进行理解,还不够. 由于指针的本质就一句话:指针就是地址.这句话大多数学过c语言的人都明白

娓娓道来c指针 (4)解析c的声明语句

(4)解析c的声明语句 在继续探索c指针之前,有必要来解析下c语言中复杂的声明语法. 只需要记住两点:一个原则,一个规则. 原则:先看标示符. 规则:运算符优先级是规则. 举例说明 1.最简单的 int array[3]; 结论:array是数组,数组规模是3,元素类型是int. 解析过程:先看标示符:array,只有一个运算符[],那么array就是数组,元素类型是int,完了. 2.难一点的 (1)数组指针 int(*array)[3]; 结论:array是一指针,指向一数组,数组规模是3,

字符指针与字符数组

学了挺久的c语言,c语言有意思的就有指针这一大块,另外就是字符串,字符指针与字符数组的区别对于初学者应该是比较难以区分的,讲讲自己的看法. 1.定义上的区别 字符数组具有固定的地址,且字符数组的名字不能更改或运算. 字符指针是一个变量,用来存储首字符的地址,且指向的字符串通常为一个常量. char str[] = "helloworld"; str[4] = 'X'; printf("%s",str); 输出结果:hellXworld char *str = &qu

指针和简单数组的结合

存储数据三个基本属性:数据的类型,数据存储的位置,数据的值. 指针介绍 定义:存储值得地址. 格式:与一般的数据定义结合形式如下:                                                                                                             Int update=5;  Int * pt;pt=&update;                                         

#运算符、不同的指针类型、数组和指针、指针运算、堆、栈、静态区、只读区、下标VS指针

#运算符:用于在预编译期将宏参数转换为字符串 #define CONVERS(x)  #x   //注:没用双引号包括. 不同类型的指针占用的内存空间大小相同. 局部变量 定义: a[5]; 打印a[i]时,a[i]为随机数. 若定义a[5]={1,2}; 打印时,a[0]=1;a[1]=2;a[2]=a[3]=a[4]=0; 数组地址与数组名: 1.数组名代表数组首元素的地址.  a=&a[0]; 2.数组的地址需要用取地址符号&才能得到 (&a) 3.数组首元素的地址值与数组的

娓娓道来c指针 (8)开发可变参数函数

(8)开发可变参数函数 在c语言中,可变参数的函数极其常见,如常用的printf().可变参数函数的一般形式如下: 返回值类型 函数名(类型1 参数1,类型2 参数2,...类型n 参数n,...); 如上所示,这是一个典型的可变参数样式,它共有n个确定的参数,最后的...表示可变参数的含义.必须指出...必须位于最后,并且它至少要有一个确定的参数,原因后面陈述. 为了开发可变参数的函数,需用到头文件stdarg.h.下面共给出两个实例,在实例中详细解释用法.一是求可变个整数的和:二是模仿pri

因为数组的地址是连续的 所以呢 可以利用指针来输出数组

//声明数组.变量和指针变量 int a[2][3],i,j; int* ip; //从键盘上为数组a赋值 for (i=0;i<2;i++) //为数组a赋值 for (j=0;j<3;j++) { cout<<"a["<<i<<"]["<<j<<"]="; cin>>a[i][j]; } //利用下标变量显示数组a for (i=0;i<2;i++) {

C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com

原文:C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 本文由 arthinking 发表于315 天前 ⁄ itzhai.com原创文章 ⁄ C语言 ⁄ 评论数 3 ⁄ 被围观 1,775 views+ 指针数组: 在一个数组中,如果它的元素全部都是指针类