*欢迎来到博主的专栏c语言进阶指南。
博主的iid(reverie_ly)*
从这里开始,我们会经常分析代码在内存中的分布形式,正所谓新手看代码,高手看内存。这也是我将这个专栏划分为进阶篇的原因,从这里开始,我们将会经常在内存层面分析代码的作用。
我们先来了解一些地址
**系统为内存中的每一字节的空间都进行了编码,这些编码被称为地址**,以一个变量的创建为例,当我们创建一个变量时,**系统会根据变量的声明来划分空间给变量**(int的数据空间为4字节,char为1字节,float为4字节)。变量在内存空间中的编码就是该变量的地址。我们可以用取地址操作符(&)得到一个变量的地址。
int a;
printf(“%p”,&a);
系统可以通过地址来访问这些数据。(在指针中会具体讲解)
**数组是一组相同类型的数据元素组成的集合。**以int arr4为例,这是一个有四个元素且每个元素都是int类型的数组
数组的形式为**type_t arr_name const_n**数组在创建的过程中【】的值必须为常量或宏,其中type_t是数组元素类型,arr_name是数组名。【】中给定的是数组的元素个数。
**数组需要初始化后才能使用,初始化的方式如下**
1)给出数组的大小且大于初始值设定个数
int arr[5]={1,2,3};
数组的初始化如下
未给定具体初始值的部分由0成为初始值。
2)数组大小小于初始值设定项
int arr[3]={1,2,3,4,5};
此时程序会报错。
3)给定初始值不给定数组大小
int arr[]={1,2,3};
数组的初始化如下
此时数组的大小为初始化项目的个数
4)字符组的大小大于字符元素的个数
char arr[5]={'a','b','c'};
初始化的结果如下
5)字符组的元素也可以是一个字符串,未给定字符组大小的字符串初始化
char ch[]="abc";
初始化结果如下
在字符串的结尾加上字符组的结束标志‘\0’
6)未给定字符组大小的字符元素初始化
char ch[]={'a','b','c'};
初始化的结果如下
!!这样初始化是有问题的,因为无法正常读取字符串的结束标志('\0'),导致字符串的长度和内容不能得知!!
同理可知,当字符组的大小等于字符串元素个数是也无法读取/0,生成字符串的长度会成为随机值
如
char ch[3]={"abc"};
printf("%s",ch);
printf("%d",sizeof(ch));//sizeof()用于计算占用空间的长度
生成的字符串和字符串长度为
这里的结果因人而异,字符串长度将会是一个随机值
可以构思一个方法给数组的某个元素初始化成有意义的值,其余值为0的情况。
如:`int arr10={0,0,0,5,0,0,0,8,0,0};
`
假设这个数组长达200个元素时如果用这种方式初始化,显然是非常的不明智的选择。在c99标准中,提供了这么一个方法
int arr[10]={[3]=2;[7]=8};
当数组进行初始化后,数组中的每一个元素都具有一个对应的下标。C语言中数组的元素下标都是从0开始的
以int arr7={1,2,3,4,5,6,7}为例,数组对应的下标为`
【】下标引用操作符。也可以认为是数组访问的操作符。使用这个符号可以访问数组的元素
int arr[7]={1,2,3,4,5,6,7}
printf(“%d ”,arr[0]);//打印1
printf(“%d ”,arr[1]);//打印2
printf(“%d ”,arr[2]);//打印3
for(int i=0;i<7;i++)
{
printf("%d",arr[i]);//打印数组下标为0~6的元素
}
for(int i=0;i<7;i++)
{
arr[i]=5;//给数组中下标0-6的元素赋值5
}
int arr[10]={1,2,3}
for(int i=0;i<10;i++)
{
printf("%p",&arr[i]);//打印每个元素的地址
}
我们可知arr数组中的元素为{1,2,3,0,0,0,0,0,0,0}10个元素。运行得到10个元素的地址为
可知每个元素的地址差恒为4,得出结论数组中的元素地址是等值递增的,递增的值为数据类型所占用的字节数。
如上述数组的数据类型为int,字节为4.所以每个元素的地址相差为4
**数组在内存中开辟是线性连续且递增的。**
在c语言中,任何变量(基本变量,指针变量,结构体变量,数组变量)的空间都是**整体开辟**,但任何元素的**起始地址**一定是**最小的**。
二维数组的形式可以理解为
设arri中,i是行,j是列。
如
int arr[4][4]={{1,2,3,4},{5,6,7,8};
二维数组的创建和格式化的规律与一维数组相似。
于此不同的点有
1)命名方式。type_t arr_name[const_n][const_n]
2)数据初始化时需要给列数给定列数大小,行数大小可忽略
进行初始化时,若无用花括号进行划分,则将**数组中的数字按顺序给入,**未给定数值的部分默认初始为0。花括号划定的部分则作为行来划定,按照花括号内的顺序来排列。
如
int arr[][4]={{1,2,3},{4,5,6}};
*下标也是从【0】开始计算。
我们用嵌套循环的方式依次求出二维数组的地址
int main()
{
int arr[2][4]={{1,2,3,4},{5,6,7,8}};
for(i=0;i<2;i++)
{
for(j=0;j<4;j++)
{
printf("arr[%d][%d]的地址是%p\n",i,j,&arr[i][j]);
}
}
}
得到的结果为:
我们可以发现二维数组的地址存储方式与一维数组类似,根据行与列的顺序依次递增。且差值为数据类型的字节数。
这里可以发现二维数组的存储方式与一维数组等同,本质上,二维数组与一维数组等同。因为在内存的存储形式上看arr3与arr12没有任何区别,也就是说对于计算机系统来说,这两个数组没有区别。我们可以用着种方式看待二维数组。以arr【3】【4】为例,我们可以将其看做是由3个元素大小为4的一维数组构成的,其中行标为数组名,即分为arr0【4】,arr1【4】,arr2【4】。
变长数组( variable-length array),C语言术语,也简称VLA。是指用 整型变量或表达式声明或定义的数组 ,而不是说数组的长度会随时变化,变长数组在其生存期内的长度同样是固定的 。
代码示例:
int n;
scanf ("%d", &n);
int array[n];
注意上述语法在C99之前是不支持的。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。