数组——C语言初阶

一.一维数组:

(1).一维数组的创建
  1. 概念:
    type_t   arr_name   [const_n];
    //type_t 是指数组的元素类型
    //arr_name 是数组的名字
    //const_n 是一个常量表达式,用来指定数组的大小
    

  2. 数组创建实例:
    #include
    int main()
    {
    	//代码1
    	int arr1[10];
    	char arr2[10];
    	float arr3[1];
    	double arr4[20];
    	//代码2
    	//用宏定义的方式
    #define X 3
    	int arr5[X];
    	//代码3
    	//错误使用
    
    	//下面的代码只能支持在C99标准的编译器上编译
    	int count = 10;
    	int arr6[count];//这种数组是不能初始化的
    	//在C99标准之前,数组的大小必须是常量或者常量表达式
    	//在C99之后,数组的大小可以是变量,为了支持变长数组
    	return 0;
    }

           注:在C99标准之前,数组的大小必须是常量或者常量表达式
                  在C99之后,数组的大小可以是变量,为了支持变长数组

(2).数组的初始化:
  1. 概念:数组的初始化是指,在创建数组的同时给数组的一些内容一些合理的初始值(初始化)。
  2. 数组是具有相同类型的集合,数组的大小(即所占字节数)由元素个数乘以单个元素的大小。
  3. 数组只能够整体初始化,不能被整体赋值。只能使用循环从第一个逐个遍历赋值。
  4. 初始化时,数组的维度或元素个数可忽略 ,编译器会根据花括号中元素个数初始化数组元素的个数。
  5. 当花括号中用于初始化值的个数不足数组元素大小时,数组剩下的元素依次用0初始化。
    字符型数组在计算机内部用的时对应的ascii码值进行存储的。
  6. 一般用”“引起的字符串,不用数组保存时,一般都被直接编译到字符常量区,并且不可被修改。
(3).一维数组的使用:
  1. 实例;
    #include 
    int main()
    {
    	int arr[10] = { 0 };//数组的不完全初始化
    	   //计算数组的元素个数
    	int sz = sizeof(arr) / sizeof(arr[0]);
    	//对数组内容赋值,数组是使用下标来访问的,下标从0开始。所以:
    	int i = 0;//做下标,此时可以是变量
    	for (i = 0; i < 10; i++)
    	{
    		arr[i] = i;
    	}
    	//输出数组的内容
    	for (i = 0; i < 10; ++i)
    	{
    		printf("%d ", arr[i]);
    	}
    	return 0;
    }
    
  2. 注意:                                                                                                                                                sizeof()操作符用于取长度,以字节为单位。sizeof(数组名)即求的时整个数组的大小。sizeof(首元素)即求数组单个元素大小。                                                                                             用0下标,是因为数组至少存在一个有效元素,所以0下标永远存在。数组是使用下标来访问的,下标是从0开始。                                                                                                                  数组的大小可以通过计算得到。建议采用sizeof(arr)/sizeof(arr[0])这种方式。

(4).一维数组在内存中的储存:
  1. 数组在内存中开辟是线性连续且递增的。
  2. 在c语言中,任何变量(基本变量,指针变量,结构体变量,数组变量)的空间都是整体开辟,但任何元素的起始地址一定是开辟字节当中最小的。


二.二维数组:

(1).二维数组的创建

二维数组创建时,行数可以忽略不写。并且所有维度的数组其第一个方括号的内容可忽略。

#include
int main() 
{
	//数组创建
	int arr1[3][4];//[行数][列数]
	char arr2[4][5];
	double arr3[2][4];
	return 0;
}
 (2).二维数组的初始化
//数组初始化
int arr[3][4] = {1,2,3,4};
int arr[3][4] = {{1,2},{4,5}};
int arr[][4] = {{2,3},{4,5}};


注意:
花括号中的一个花括号代表一个一维数组的初始化。当里面无花括号分组时,按照顺序从第一个开始逐个进行初始化。余下的未赋值的元素用0初始化。
 

(3).二维数组的使用 
  1. 二维数组的使用也是通过下标的方式,用双重循环嵌套进行索引使用。
  2. 二维数组中数的查找:
    #include
    int main()
    {
    	int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
    	printf("%d", arr[1][2]);
    	//二维数组中数下标是这样规定的
    	//00 01 02 
    	//10 11 12 
    	//20 21 22 
    	//如此输出便是6
    	return 0;
    }
  3. 二维数组中打印整个数组:
    #include
    int main()
    {
    	int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
    	int i = 0;
    	for (i = 0; i < 3; i++)
    	{
    		int j = 0;
    		for (j = 0; j < 4; j++)
    		{
    			printf("%d ", arr[i][j]);
    		}
    		printf("\n");
    	}
    	return 0;
  4. 二维数组中重新为数组赋值:
    #define _CRT_SECURE_NO_WARNINGS
    #include
    int main()
    {
    	int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
    	int i = 0;
    	for (i = 0; i < 3; i++)
    	{
    		int j = 0;
    		for (j = 0; j < 4; j++)
    		{
    			scanf("%d ", &arr[i][j]);
    		}
    	}
    	for (i = 0; i < 3; i++)
    	{
    		int j = 0;
    		for (j = 0; j < 4; j++)
    		{
    			printf("%d ", arr[i][j]);
    		}
    		printf("\n");
    	}
    	return 0;
    }

(4).二维数组在内存中的储存
  1. 二维数组在内存的空间布局上,也是线性连续且递增的!!!
  2. 二维数组本质上也是一维数组,只不过内部元素放的是一维数组

.

三.数组越界:

  1. 数组的下标是有范围限制的。
  2. 数组的下规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。
  3. C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的,所以程序员写代码时,最好自己做越界的检查数组——C语言初阶_第1张图片
  4. 二维数组的行和列也可能存在越界:数组——C语言初阶_第2张图片


四.数组作为函数参数:

  1. 调用函数传参数组时,减少函数传数组时的成本问题(时间和空间)。因为传参时,需要临时拷贝,如果数组过大,可能会浪费资源,严重的话可能栈溢出。
  2. 数组元素降维成指向数组内部元素类型指针
  3. 对指针加一,加上所指向的类型的大小。

例题:往往我们在写代码的时候,会将数组作为参数传整个函数,比如我要实现一个冒泡排序函数,将一个整型数组排序。

代码如下:

#include
//形参是数组的形式;
void popo(int arr[], int n)
//数组名本质上是数组首元素的地址,地址是应该使用指针来接收
//所以arr[]看似是数组,本质上是指针变量
{
	//趟数
	int i = 0;
	for (i = 0; i < n - 1; i++)
	{
		//一趟冒泡排序
		int j = 0;
		for (j = 0; j < n - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				//交换
				int x = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = x;
			}
		}
	}
}
int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	int n = sizeof(arr) / sizeof(arr[0]);
	popo(arr,n);
	int i = 0;
	for (i = 0; i < n ; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

总结:

  1. 形参格式,例如int arr[ ]或者int *arr,两者等价
  2. 形参元素个数可被忽略,并且建议忽略(有可能改变了实参的大小,这样比较方便)。或者也可以填写比实参元素个数大的值。
  3. sizeof()求数组元素个数时,尽量在数组定义时求。因为传参后数组会降维成指针。

五.数组名:

(1).一维数组数组名:

数组名确实能表示首元素的地址,但是有两个例外:

  1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节
  2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址

数组——C语言初阶_第3张图片

(2).二维数组数组名:

二维数组的数组名也表示数组首元素的地址(这里的首元素是指第一行元素地址)

数组——C语言初阶_第4张图片

你可能感兴趣的:(c语言,开发语言)