C语言基础 -数组

 首先:数组:数组是一组相同类型元素的集合

一维数组:存储一串或者一行数据

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

1.1数组的创建

int arr[10] = {0};
//type_t arr_name [const_n} 形式

tupe_t   是指数组的元素类型  比如一组数都是整型   那么type_t就是 int   
 arr_name  数组名。可以自己定,一定要相对有意义
 const_n   是一个常量表达式用来指定数组的大小,不一定要是数字。
 注意:数组创建,在c99标准之前,数组大小只能是常量表达式
 c99标准中引入了变长数组的概念。使得数组在使用的时候可以使用变量,但是数组不能初始化。
 局部变量存储在栈区,不符值,不初始化是随机值。 这个可以在gcc编译器去体验一下

1.2数组的初始化

 数组的初始化:创建数组的时候给数组的内容一些合理初始值(比如初始化为0)。

 数组初始化用大括号,中间元素用逗号隔开。
 

 //形式:
 int arr[10}= {10,2,3,4,5,6,7,8};  //这种数组大小和元素相对应的叫完全初始化
 int  arr[10] = {1,2,3} ;  //这种叫做不完全初始化,剩下的元素都是0
 int  arr[10] = {0};//  把数组初始化为0,不完全初始化
 int arr6[]  ;// 不完全类型,错误写法 
 char arr1[] = “abc" ;// 这个叫省略数组大小的时候,数组必须初始化,数组的大小是根据数组的内容决定的,有几个元素就是多大
 //字符串的特殊形式,这种也叫字符串的初始化,因为字符串数组是拿来存字符串的所以可以这样存 
 char arr2[3]= {'a','b','c'} ,// 上下两种存储的区别
 //char arrr1 是中存储了四个元素  a,b,c /0   多了一个字符串的结束标志
  char arr2  中只有3个元素    a,b,c 
 
 char arr3[10] = {"a",98,"c"} ;// arr2和arr3是一样的,98就是b的acsii码值

 1.3一维数组的使用

 [] 为下标引用操作符,,就是数组访问的操作符。
 C语言规定,数组的每一个元素都有一个下标,元素的下标是从0开始的。
 整个数组大小的求法:sizeof(arr)  数组名和数组第一个元素保存的是数组的地址。
 单个数组元素的大小 sizeof(arr[0])。
 两者相除就是数组的长度单位,再减1就是数组的最大下标。
 ps:为什么不用strlen,strlen是求字符串长度的。

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	//   元素下标   0 1 2 3 4 5 6 7 8 9
	printf("数组中第五个元素是:%d", arr[5]);//[]下标引用操作符
	return 0;
}

运行结果如图: 

如何访问到一维数组当中的每一个元素呢

答:使用for循环遍历

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	//   元素下标   0 1 2 3 4 5 6 7 8 9
	int sz = sizeof(arr) / sizeof(arr[0]);//数组长度10
	//整个数组大小的求法:sizeof(arr)  数组名和数组第一个元素保存的是数组的地址
	//单个数组元素的大小 sizeof(arr[0]);
	//两者相除就是数组的长度单位,在减1就是数组的最大下标
	//	strlen是求字符串长度的
	int  i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);//什么使用for循环的时候数组的大小可以使用变量,  注意c99规定的是在数组创建的时候,数组大小只能是常量,但是这是在访问元素,下标可以用变量
	}
	return 0;
}

运行结果:

1.4 数组在内存中的存储

一维数组在内存中的存放是连续的 随着下标增长,地址是由低到高。

方法:看布局,看每个元素的地址,为了直观看出数组元素在内存中的分布,直接循环打印出元素的地址。

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	//   元素下标   0 1 2 3 4 5 6 7 8 9
	int sz = sizeof(arr) / sizeof(arr[0]);//数组长度10
	//整个数组大小的求法:sizeof(arr)  数组名和数组第一个元素保存的是数组的地址
	//单个数组元素的大小 sizeof(arr[0]);
	//两者相除就是数组的长度单位,在减1就是数组的最大下标
	//	strlen是求字符串长度的
	int  i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("&arr[%d] == %p\n",i, arr[i]);//什么使用for循环的时候数组的大小可以使用变量,  注意c99规定的是在数组创建的时候,数组大小只能是常量,但是这是在访问元素,下标可以用变量
	}
	return 0;
}

结果如下:C语言基础 -数组_第1张图片

注明:a是16进制中的10 

 二,二维数组的建立和初始化

 二维数组:存储一组数据

2,1二维数组创建及初始化:

数组类型 数组名[行数][列数] 

a.int arr[3][4] = {{3,4,5,7},{5, 6, 7, 6} ,{1,2,3,5}} 一行一个大括号区分。
 b. int arr[3][4] = {1,2,3,4,5,6,7,8,6,7,8,9}  这种初始化方式它会首先一行一行的放满再放下一行  不完全初始化,不够后面补0,单独一行括起来,够就走下一行,不够就补0。
 c.int arr[3][4] = {{1,2,3}4,5,6,7,8,6,7,8,9} 这种第一行就补0,不建议,要括就都括 。
 二维数组即使初始化了,行可以省略但是列可以省略,理由见下文内存。

 int arr[3][4] = {{3,4,5,7},{5, 6, 7, 6} ,{1,2,3,5}};// 一行一个大括号区分
  int arr[3][4] = {1,2,3,4,5,6,7,8,6,7,8,9};//  这种初始化方式它会首先一行一行的放满再放下一行  //不完全初始化,不够后面补0,单独一行括起来,够就走下一行,不够就补0
 c.int arr[3][4] = {{1,2,3}4,5,6,7,8,6,7,8,9} ;//这种第一行就补0,不建议,要括就都括 
 二维数组即使初始化了,行可以省略但是列可以省略
 

 2.2 二维数组的使用

  [] 为下标引用操作符,,就是数组访问的操作符。

 二维数组的元素访问是通过预算所在行数列数的下标来确定的,行数和列数都是从0开始的

二维数组的元素访问直观图:

C语言基础 -数组_第2张图片

int main()
{
	
		
			int arr[3][4] = { {3,4,5,7},{5, 6, 7, 6} ,{1,2,3,5} };
			
			int i = 0;
			int j = 0;
			for (i = 0; i < 3; i++)//控制行数
			{
				for (j = 0; j < 4; j++)
				{
					printf("%d ", arr[i][j]);//控制列数
				}
				printf("\n");
			}
	return 0;
}

2.3 二维数组在内存中的存储

 二维数组在内存中的存储也是连续存储的 一条龙存储

int main()
{
	int arr[3][4] = { {3,4,5,7},{5, 6, 7, 6} ,{1,2,3,5} };
		
		int i = 0;
		int j = 0;
		for (i = 0; i < 3; i++)//控制行数
		{
			for (j = 0; j < 4; j++)
			{
				printf("%d ", arr[i][j]);//控制列数
			}
			printf("\n");
		}
		//打印地址看内存分布
		for (i = 0; i < 3; i++)//控制行数
		{
			for (j = 0; j < 4; j++)
			{
				printf("&arr[%d][%d] = %p \n",i,j, &arr[i][j]);//控制列数
			}
			
		}
		
		
	return 0;
}

结果分析:

 C语言基础 -数组_第3张图片

 可以看出,二维数组的内存也是一整块开辟,数组中的每个元素的位置都是相邻的。地址从小到大连续存储。所以可以解释为什么数组的存储中行可以省略,列不可以省略,因为是连续存储,只有知道第一行存放在那个位置,才能知道下一行放在哪里,行里面的元素个数是列决定的。

二维数组的个人理解:二维数组可以看做是每一行当做一个一维数组当做元素的数组 C语言基础 -数组_第4张图片

 三, 数组越界

数组的下标是有范围限制的,
 数组的下标规定是由0开始,如果有N个元素,最后一个元素是N-1
 所以数组下标如果小于0或者大于N-1,就是数组越界访问了,超出了数组合法空间的访问
 C语言本身不检查数组的越界,编译器也不一定报错,但是不代表程序没错,自己做越界检查

四,数组作为函数参数 

数组传参,传的是地址,自编函数里面虽然是个参数数组(也可以改为指针)在接收值

但是还是相当于指针所以数组的长度的求法在定义函数的外部求,带到自编函数来求就会产生bug 。所以建议如果自定义函数里面要用到数组的长度的时候,尽量在main函数内求出数组长度作为参数一起传递。

数组名知识补充:

1.sizeof(数组名),计算整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数组

2.&数组名,取的是数组的地址。&数组名,数组名表示整个数组

除了上面两种情况以外,所有的1数组名都表示数组首元素的地址。

总结:数组名表示两种情况,1是整个数组,2表示首元素的地址。但是只有上述两种情况满足1. 

(注意事项的解释放在文章冒泡算法初了解中具体看)

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