C语言——数组入门

目录

数组

数组是什么?

一维数组的创建和初始化

一维数组的创建

一维数组的初始化

访问一维数组中的元素

一维数组在内存中的存放

 二维数组的创建和初始化

二维数组的创建

二维数组的初始化

访问二维数组中的元素

二维数组在内存中的存放

 数组越界 


数组

1.数组是什么?

数组是一组相同类型元素的集合。   

比方说将int类型的1、2、3、4、5放在一个数:int arr[5]={1,2,3,4,5}

2.一维数组的创建和初始化


2.1一维数组的创建

type_t  arr_name [const_n]
//type_t     元素类型 int、char等
//arr_name   数组名      
//[const_n]  数组大小 :是一个常量表达式,用于指定数组的大小
             []叫做下标引用操作符   
int main()
{
	int arr[10];    //整形数组的创建
	char arr[5];    //字符数组的创建
    char arr[3+2]    //用表达式指定数组大小


    //特殊情况:    //用变量表示数组大小
    int n;
    scanf("%d",&n);
    int arr[n];    //设置一个变量,通过手动输入控制数组大小

}

注意:

//①在C89、C90的标准中,不允许使用变量表示数组的大小。

        int arr[] ; []中只能给一个常量:4、10、100等(可以是计算式:3+2等)

//②C99后,添加了“变长数组”这一概念,此后可以使用变量指定数组大。

        例如:int n ; scanf("%d",&n) ; int arr[n];

//③目前仍有一些开发环境不支持C99的“变长数组”,例如:VS2019、VS2022


2.2一维数组的初始化

什么是初始化?

在一维数组被定义的时候,就给数组赋一些初始元素。

例如:int  arr[5] = {1,2,3,4,5};         定义了一个整形数组 arr,大小为5,初始元素有1,2,3,4,5

int main()
{
	int arr1[10] = { 1,2,3 };    //不完全初始化,剩余的元素默认为0;
	int arr2[5] = { 1,2,3,4,5 };    //完全初始化

	char arr3[3] = { 'a',98,'c' };    //98是字符b对应的ASCII码值
	char arr4[3] = { 'a','b','c' };    //这两个数组元素相同


	int arr5[] = { 1,2,3 };     //完全初始化时,可以省略数组大小,自动根据初始化元素配置大小
例如:int arr6[] = { 0 };    //数组大小为1,元素为0
      int arr6[]={1,3,5};    //数组大小为3,元素为1、3、5      

	char arr7[] = { 'a','b','c' };    //数组内没有'\0'
	char arr8[] = "abc";            //字符串自带结束标记"\0"
    //实际上arr8[]={'a','b','c','\0'};

	return 0;
}

//对于一个已经被初始化了数组,但是你不知道这个数组的大小,这时一定有人会一个元素一个元素的去数,其实有更简单也更符合标准的办法,那就是使用sizeof

原理:用整个一维数组的在内存中占用的字节数,除以一个元素占用的字节数,就得到了元素个数

int main()
{
    int arr[]={1,2,4,9,10,15,34,20,18,37};
    int len=sizeof(arr)/sizeof(arr[0]);   //sizeof(arr)计算原理,本文下面有论述
    printf("%d",len);    
    //打印结果实际为10,上述数组的元素个数的确为10
}

3.访问一维数组中的元素

想必你也发现了:对于数组 arr[10],[] 其实是一个操作符,叫做下标引用操作符

[] 的使用方式为:一个数组名 + 下标索引值

如此便可以实现对数组中元素的访问。

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };    //C语言规定,数组的下标从0开始				
                //0,1,2,3,4,5,6,7,8,9	    此为下标值

  //通过下标打印数组中的元素:
	printf("%d\n", arr[6]);    //打印结果为7

  //通过下标修改对应元素的值:(也可以说是赋值)
	int i = 0;
	int  sz = sizeof(arr) / sizeof(arr[0]);    //获取元素个数
	for (i = 0; i < sz; i++)
	{
        arr[i] = 10 - i;	 //例如将元素大小与i的值挂钩
    }

	for (i = 0; i < sz; i++)	//打印下标对应的元素
		printf("%d ", arr[i]);
    //打印结果为10 9 8 7 6 5 4 3 2 1 
}

4.一维数组在内存中的存放

数组在内存中是怎么存放的呢?

我们首先用以下代码打印数组中每个元素的地址。

//我们使用&获取数组在内存中的地址:
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int i = 0;
	int  sz = sizeof(arr) / sizeof(arr[0]);    //获取元素个数

    for (i = 0; i < sz; i++)
	    printf("&arr[%d]=%p\n", i, &arr[i]);    //打印地址
}

打印结果如下:

注意:为了便于观察使用的是32位的机器打印、地址是以16进制的形式打印出来,单位是字节

上图打印结果显示:数组中每个元素见地址相差   4   ,而这正好是 int 类型在内存中占用的空间

//    //说明1:数组在内存中是连续存放的
//    //       2:随着下标的增长,地址是由低到高变化的

 5.二维数组的创建和初始化


5.1二维数组的创建

类似于一维数组:

type_t arr_name [const_m][const_n]

//type_t     元素类型 int、char等
//arr_name   数组名      
//[const_m]  数组行索引:是一个常量表达式,用于指定数组的行数
//[const_n]  数组列索引:是一个常量表达式,用于指定数组的列数
             []叫做下标引用操作符 
//注意二维数组实际上是没有行列之分的,只是便于描述,便于理解才这样称呼的
int main()
{
	int arr[3][4];
	char arr1[2][5];
	
}

5.2二维数组的初始化

与一维数组有相同点:

int main()
{

	
	int arr2[3][5] = { 0 };    //所有元素均为0;

	int arr3[3][5] = { 1,2,3,4,5,11,12,13,14,15,21,22,23,24,25 };//完全初始化,先行后列

	int arr4[3][5] = { {1,2,3},{ 2,3,4,5} ,{ 3,4,5,6,7 } };//指定行元素内容,多余位置为0

	int arr5[][10] = { {1,2},{2,3,4},{5,5,5} };//有3行,每一行10个元素,未被初始化的元素默认为0
	
    //对于二维数组,若进行初始化,则行标可以省略,列标不能省略

	//行标和列标都是从0开始的

	//知道行标和列标就可以访问指定元素



}

需要注意的点:

①二维数组标明行标和列标后,初始化的元素会自动按照行列分配

②可以在初始化时,指定某一行放哪些元素,若该行有剩余的位置,则默认为0

③二维数组的行标可以省略,列标不能省

6.访问二维数组中的元素

类似于一维数组:

若想访问二维数组中的元素,也需要使用下标引用操作符:[]

访问方式为一个数组名 + 行标索引值 + 列标索引值

int main()
{
	int i, j;
	int arr[2][3];
	for (i = 0; i < 2; i++)
	{
		for (j = 0; j < 3; j++)
			scanf("%d", &arr[i][j]);	//从每一行的每一列依次 录入元素
	}

    //假设我们输入的是1,2,3,4,5,6
	for (i = 0; i < 2; i++)
	{
		for (j = 0; j < 3; j++)
			printf("%d ", arr[i][j]);	//从每一行的每一列依次 打印

		printf("\n");				    //体现每一行,实际存放时,并没有行列之分,而是连续存放
	}

运行结果如下:


7.二维数组在内存中的存放

 同样地,这里使用取地址运算符&,获得每个元素的地址:

int main()
{    
	int i, j;
	int arr[2][3] = { 1,2,3,4,5,6 };

    for (i = 0; i < 2; i++)
	{
	for (j = 0; j < 3; j++)

		printf("&arr[%d][%d]=%p\n", i, j, &arr[i][j]);
	}

}

运行结果如下:

可以发现

元素的地址之间也是正好相差 4 个字节

说明在二维数组中,元素是依次在地址中排列的,没有所谓行列分布

期望排布:                                                        实际排布:

                          因此,二维数组中,所有元素在内存中都是连续存储的,在内存中不存在行列之分

二维数组其实是 一维数组的数组
///即:二维数组内存放的是多个一维数组
这个一维数组元素个数就是列标
一维数组的数组名就是arr[0]、arr[1]....



 8.数组越界 

 什么是数组越界呢?

我们都知道,内存是连续的线性空间,当我们创建数组时,会向内存申请存储空间用于存放数组

例:int  arr[10] = {1,2,3,4,5,6,7,8,9,10};

 这个数组的下标从0开始,范围【0,10)也就是0—9的下标。当使用这个范围以外的下标值访问时,便会产生数组越界。

由于我们不知道范围外存放的是什么、也不知该区域是否允许访问。当我们访问时便可能产生或大或小的问题。

当我们在写程序时,如果存在越界访问,编译器在编译时并不会报错,程序会照常运行,但是运行结果往往是错误的,例如:

int main()
{
    int i=0;
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };    //下标范围:0-9

	for (i = 0; i <= 10; i++)	//i=10时,发生越界访问
	{
		printf("%d ",arr[i]);	//打印结果会发生错误
	}
    printf("\n\n");
	//编译器一般不会发现数组越界访问的操作,所以程序能运行
	

程序运行结果如下:

//所以程序员写代码时,注意要防止越界访问的操作出现。


  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值