当前位置:网站首页>C语言-数组
C语言-数组
2022-08-05 08:46:00 【Dontflinch】
文章目录
前言
浅谈数组
一、数组如何初始化
这里我将 数组的初始化方式举例(一维数组):
int arr1[10] = {1,2,3};
这样创建出来的数组是这样的
它将1,2,3赋给前面三个空间后,后面七个空间自动赋值为0;
int arr2[] = {1,2,3,4};
赋值结果为
这里我们可以看出,这样赋值得到的是通过后面我们给出的值而分配的数组长度。我们只给了四个值,那么数组就只分配了四个空间。
char arr6[] = “abcdef”;
赋值结果为
我们可以看到这样赋值数组会自动将字符一个一个拆开放入数组中,并且会在最后一个字符后面再放入一个’\0‘,这个字符是数组结束的标志。
ps:字符\0与数字0是不一样的,字符\0的ASCII码值是0,而0的ASCII码值不为0
二、一维数组的操作符"[]"
“[]”是下标引用操作符,它的作用是访问数组的元素
例如:arr[4]就是访问数组下标为4的元素,数组下标用0开始编号,下标为4,即为第5个元素。
三、数组大小的计算
int arr[10]
int sz = sizeof(arr)/sizeof(arr[0]);
这段代码通过先计算数组的总字节数,再除以一个元素的所占字节数,就得到了数组的大小。
四、一维数组在内存中的存储
数组在地址中是连续存放的。以int arr[4]为例子
若首元素地址为x,则&arr[1]的地址即为x+4;因为一个int型的大小为4,故地址要往后移动4个字节,若为char,则往后移动一个字节
代码示例:
#include<stdio.h>
int main()
{
int arr[4] = {
1,3,5,6 };
for (int i = 0; i < 4; i++)
{
printf("%p \n", &arr[i]);
}
return 0;
}
这段代码的作用是打印出各个数组元素的地址,执行结果如下
我们可以看到第一个元素的地址要比第二个元素地址少4,第二个元素地址要比三个元素地址少4.如此我们可以推断出,数组元素的地址是由低到高的
五、二维数组的创建和初始化
二维数组是一维数组的更高一个维度,下面是二维数组创建的实例
int a[3][4] = {1,2,3,4};
int a[3][4] = { {1,2},{3,4}};
int a[][4] = {1,2,3,4,5};//给二维数组赋值时,可以省略第一个方括号里的值。其原因后面解释
六、二维数组在内存中的存储
代码示例:
#include<stdio.h>
int main()
{
int a[3][3];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
printf("%p\n", &a[i][j]);
}
}
return 0;
}
我们通过这段代码对二维数组的每一个元素的地址进行打印。
打印结果:
我们可以清晰的看到每一个元素的地址都是前一个元素的地址加4;
如此我们可以推断出虽然二维数组叫二维,但在内存存储中仍然是一维的,与一维数组的存储相差无几
七、数组访问越界
这个其实非常好理解,比如你创建了int arr[3]的数组,你却要访问arr[4],这在原本初始化数组的时候就没有为其分配第5个元素的地址,只有3个元素的地址,这就是数组访问越界
数组的下标是有范围限制的。
数组的下规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。
所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。
C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的,
所以程序员写代码时,最好自己做越界的检查
八、数组初始化的特殊样式
前面我们说过 ‘[ ]’ 是一个操作符,我们以操作符的角度去理解它,我们以 ‘+’ 号为例:
3+4 我们可以写成 4+3;而int a[3] 我们也可以写成 int 4[a];
这样我们可以得到一种新的初始化方式:
int 4[a] = {1,2,3,4};
这样看起来非常奇怪,但是它是正确的:
同时我们上面提到二维数组赋值的时候可以忽略掉第一个括号里的数字,而不能忽略掉第二个括号里的数字,原因是,第二个括号里的数字决定的是列数,如果把列数忽略了,当你在赋值时,数组不知道何时开始给第二行的数组赋值,这样数组的大小就不确定,自然而然列数就必须确定。但是行数不一样,当列数确定时,行数可以由赋值的个数来决定。这样赋值出来的数组的大小也是确定的
九、数组名是什么?
我们在日常的代码中经常能看到数组名作为参数,
例如:函数传参的时候,将数组传进去传的是数组名
那么数组名到底是什么呢?
实际上,数组名代表的是数组的首地址,也就是说,函数传参时,传的数组名其实是数组的首元素地址,但是这里有两个特殊的地方:
一、sizeof(arr)
二、&arr
第一个情况:sizeof(arr);为什么特殊呢,我们想一想,若arr为首元素的地址,那为什么sizeof(arr)算的是整个数组所占的字节数呢。实际情况确实如此,arr确实为首元素的地址,但是算的是整个数组的长度。所以将它列为特殊情况
第二个情况:&arr;那么这个为什么特殊呢,我们来看一段代码
#include<stdio.h>
int main()
{
int arr[3] = {
1,2,3 };
printf("arr[0]的地址为%p\n", &arr[0]);
printf("arr[0]+1的地址为%p\n", &arr[0]+1);
printf("arr的地址为%p\n", &arr);
printf("arr+1的地址为%p\n", &arr+1);
return 0;
}
这段代码的作用是打印arr[0]的地址及其+1的地址,和arr的地址及其+1的地址,打印结果如下
我们可以看到,虽然&arr[0]的地址和&arr的地址一样,但arr[0]+1的地址为arr[0]的的地址加4,即一个整型,但&arr+1的地址为&arr的地址加12,即三个整型,也就是说,&arr+1是向后跳整个数组,而&arr[0]是向后跳一个整型;
边栏推荐
猜你喜欢
Spark cluster deployment (third bullet)
使用HBuilder离线本地打包ipa教程
spark集群部署(第三弹)
国际原子能机构总干事称乌克兰扎波罗热核电站安全形势堪忧
Undefined symbols for architecture arm64解决方案
DPU — 功能特性 — 网络系统的硬件卸载
CVPR 2022 | 将X光图片用于垃圾分割,港中大(深圳)探索大规模智能垃圾分类
XSS靶机通关以及XSS介绍
Detailed explanation of DNS query principle
XCODE12 在使用模拟器(SIMULATOR)时编译错误的解决方法
随机推荐
Ethernet Principle
“充钱”也难治快手的“亏亏亏”?
ps怎么把图片变清晰,自学ps软件photoshop2022,简单快速用ps让照片更清晰更有质感
MySQL database error The server quit without updating PID file (/var/lib/mysql/localhost.localdomain.pid)
sphinx matches the specified field
嵌入式系统:基本定时器
使用稀疏 4D 卷积对 3D LiDAR 数据中的运动对象进行后退分割(IROS 2022)
MM上街前的折腾(有趣)
软件系统测试和验收测试有什么联系与区别?专业软件测试方案推荐
苹果官网商店新上架Mophie系列Powerstation Pro、GaN充电头等产品
Xcode10的打包方式distribute app和启动项目报错以及Xcode 打包本地ipa包安装到手机上
nn.unfold和nn.fold
网页直接访问链接不让安全中心拦截
Linux导出数据库数据到硬盘
Iptables implementation under the network limited (NTP) synchronization time custom port
数据源对象管理Druid和c3p0
使用HBuilder离线本地打包ipa教程
Three solutions to solve cross-domain in egg framework
The Secrets of the Six-Year Team Leader | The Eight Most Important Soft Skills of Programmers
Spark cluster deployment (third bullet)