数组(Array)是一系列具有相同类型的数据的集合,每一份数据叫做一个数组元素(Element)。
数组中的所有元素在内存中是连续排列的,整个数组占用的是一块内存。
以int arr[] = { 99, 15, 100, 888, 252 };
为例,该数组在内存中的分布如下图所示:
数组名可以认为是一个指针,它指向数组的第 0 个元素。在C语言中,我们将第 0 个元素的地址称为数组的首地址。以上面的数组为例,下图是 arr 的指向
数组名的本意是表示整个数组,也就是表示多份数据的集合,但在使用过程中经常会转换为指向数组第 0 个元素的指针,
所以上面使用了“认为”一词,表示数组名和数组首地址并不总是等价。初学者可以暂时忽略这个细节,
把数组名当做指向第 0 个元素的指针使用即可
sizeof(arr) 会获得整个数组所占用的字节数,sizeof(int) 会获得一个数组元素所占用的字节数,它们相除的结果就是数组包含的元素个数,也即数组长度。
arr 是数组名,指向数组的第 0 个元素,表示数组首地址, arr+i 指向数组的第 i 个元素,*(arr+i) 表示取第 i 个元素的数据,它等价于 arr[i]。
arr 是 int*
类型的指针,每次加 1 时它自身的值会增加 sizeof(int),加 i 时自身的值会增加 sizeof(int) * i
#include <stdio.h> int main(){ int arr[] = { 99, 15, 100, 888, 252 }; int len = sizeof(arr) / sizeof(int); //求数组长度 printf("Size of len = %d\n", len ); printf("Size of int = %d\n", sizeof(int)); printf("Size of array = %d\n", sizeof(arr)); int i; for(i=0; i<len; i++){ printf(" %d th time = %d\n", i, *(arr+i) ); //*(arr+i)等价于arr[i] } return 0; }
Size of len = 5
Size of int = 4
Size of array = 20
0 th time = 99
1 th time = 15
2 th time = 100
3 th time = 888
4 th time = 252
如果一个指针指向了数组,我们就称它为数组指针(Array Pointer)。
arr 本身就是一个指针,可以直接赋值给指针变量 p。arr 是数组第 0 个元素的地址,
所以int *p = arr;
也可以写作int *p = &arr[0];
。也就是说,arr、p、&arr[0] 这三种写法都是等价的,它们都指向数组第 0 个元素,或者说指向数组的开头。
#include <stdio.h> int main(){ int arr[] = { 99, 15, 100, 888, 252 }; int *p = arr; printf("%u\n",arr[0]); printf("%u\n",arr); printf("%u\n",&arr); printf("%u\n",*p); printf("%u\n",p); }
99
3676766512
3676766512
99
3676766512
再强调一遍,“arr 本身就是一个指针”这种表述并不准确,严格来说应该是“arr 被转换成了一个指针”。这里请大家先忽略这个细节,我们将在VIP教程《数组和指针绝不等价,数组是另外一种类型》和《数组到底在什么时候会转换为指针》中深入讨论。
数组指针指向的是数组中的一个具体元素,而不是整个数组,所以数组指针的类型和数组元素的类型有关,
上面的例子中,p 指向的数组元素是 int 类型,所以 p 的类型必须也是int *
。
#include <stdio.h> int main(){ int arr[] = { 99, 15, 100, 888, 252 }; int i, *p = arr, len=sizeof(arr)/sizeof(int); printf("%d\n", *p); //解指针 printf("P = %d\n", p); //存的是地址 printf("P+1 = %d\n",p+1);//存的是地址 printf("&p = %d\n", &p); // 指针的地址 printf("arr = %d\n", arr); //第0元素 首地址 printf("arr[0] = %d\n", arr[0]); printf("&arr[1] = %d\n", &arr[1]); printf("&arr[0] = %d\n", &arr[0]); printf("arr+1 = %d\n", arr+1); for(i=1; i<len; i++){ printf("%d\n", *(p+i)); } return 0; }
#include <stdio.h> int main(){ int arr[] = { 99, 15, 100, 888, 252 }; int i, *p = arr, len = sizeof(arr) / sizeof(int); printf("%d\n ", *p); // 99 printf("%d ", sizeof(p)); // 8 printf("\n"); for(i=0; i<len; i++){ printf("%d ", *p++ ); } //99 15 100 888 252 printf("\n"); printf("%d\n", sizeof(arr)); // 20 printf("%d, %d, %d, %d, %d \n", *p,p,++p,p++,&p ); // 5, 746887612, 746887612, 746887604, 746887576 printf("\n"); for(i=0; i<len; i++){ printf("%d ", *++p ); } //4199040 0 -383549285 32620 0 return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)