1.一维数组 1.1数组的创建
数组是一组相同类型元素的集合。数组的创建方式:
type_t arr_name [const_n]; //type_t是数组的元素类型 //arr_name是数组的名字 //const_n是一个常量表达式,用来指定数组的大小。
创建数组的实例:
int arr1 [10]; float arr2 [5]; short arr3 [20]; char arr4 [3]; int n = 1; int arr5 [n]; //在c99之前,[]中必须为常量,但在c99中,可以放入变量--支持变长数组的概念。1.2数组的初始化
数组再创建的同时,我们可以给它一个值。就叫做数组的初始化。
int arr1 [10] = {1,2,3,4,5,6,7,8,9,10};
//完全初始化
int arr1 [10] = {1,2,3};
//不完全初始化,默认其他元素初始值为0
int arr [] = {1,2,3};
//只要初始化,大小可以不指定。大小根据元素的数目创建。
char ch [] = {'a',98,'c'};
//98是字符b的ASCII码值,相当于'b'
char ch0 [] = “abc”;//实际上有a b c 四个元素
char ch1 [] = {'a','b','c'};//有a b c 三个元素
通过最后两个代码,可以引入sizeof和strlen的区别:
strlen是一个库函数,计算的是字符串的长度,仅仅针对字符串,关注字符串中是否有 ,计算的是 之前的字符个数;而sizeof是一个操作符,是用来计算变量所占内存空间大小的,任何类型的数据都可以使用,只关注空间大小,不在乎内存中是否存在 。
在这里strlen就是计算字符串长度,不计算 ,而字符串的结束标志是 ,而ch2中没有 ,于是便是后面便是计算机分配的随意值直到到 后才结束,所以是15.。
1.3数组的使用数组的使用可以使用[ ]这个下标引用操作符来访问数组:
需要注意一点下标是从0开始的,之后连续下去
int main()
{
char ch [10] = { 1,2,3,4,5,6,7,8,9,10 };
//计算数组的长度
int sz = sizeof(ch) / sizeof(ch[0]);
printf("%dn", sz);
//访问数组中每一个元素
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%dn", ch[i]);
}
//向数组中放入元素
int j = 0;
for(j = 0; j < sz; j++);
scanf("%d",&arr[i]);
return 0;
}
1.4一维数组在内存中的储存
举个实例来看看元素的地址
int main()
{
int ch[10] = { 0,5,2,3,4,7,8,9,6,1 };
int i = 0;
int sz = sizeof(ch) / sizeof(ch[0]);
for(i = 0; i < sz; i++)
printf("%pn", &ch[i]);
return 0;
}
每个地址间差4位,是因为int整形数据占四个字节,一个字节给一个地址,而地址只是指向所占第一个字节。所以各差4位。从这里我们可以看出,数组在内存中的存储连续的。
2.二维数组 2.1二维数组的创建不同于一维数组,二维数组是有行列的。
int ch [3] [4];2.2二维数组的初始化
//完全初始化
int ch [3] [4] = {1,2,3,4,5,6,7,8,9,10,11,12};
//不完全初始化,会按顺序存储进去,其余的默认为0
int ch [3] [4] = {1,2,3,4,5};
int ch [3] [4] = {{1,2,},{3,4},{5,6}};
//这样的话,第一行前两个就是1,2;第二行前两个就是3,4;第三行前两列就是5,6
//二维数组可以不初始化行,但是必须初始化列
2.3二维数组的使用
和一维数组一样,都是通过下标操作符[]来访问数组的:
//int ch [行] [列],类似于坐标
int main()
{
int ch[3][4] = { 1,2,3,4,5,6,7,8 ,9,10,11,12 };
int i, j;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
printf("%dn", ch[i][j]);
}
return 0;
}
2.4二维数组在内存中的储存
与一维数组相同,都是按顺序储存的,储存完一行到下一行。可以想象成是一维数组的数组。
int main()
{
int ch[3][4] = { 1,2,3,4,5,6,7,8 ,9,10,11,12 };
int i, j;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
printf("%pn", &ch[i][j]);
}
return 0;
}
3.数组溢出
数组的下标是有范围限制的,数组下标是从0开始到n-1(数组中有n个元素),如果超出这个范围就是数组越界访问了,超出了数组合法空间的访问。而且在C语言中,它是不做数组下标的越界检查,编译器也不一定报错,但不意味着程序就是正确的,所以在写代码时要尤其注意数组越界!
数组在内存中是连续存储的,所以在第一个元素最后一个元素后也是有数据的:
越界访问到了其他的数据,所以在10后会打印其他奇奇怪怪的数字~
4. 数组可以作为函数的参数 第一种冒泡排序函数
在构造一个函数的时候,数组也可以作为参数传给函数。举一个实例--实现一个冒泡排序函数,将一个整形数组排序。冒泡排序就是两两相邻的元素比较,如果大小符合要求互换数据。
先看这个 代码是否正确:
运行结果
并没有起到排序的作用,经过调试发现是sz为1,致使后面的循环进不去。我们由此推断sizeof(arr)大小是4。为什么是这样的?那就不得不提数组名的含义了:
数组名是什么?数组名是数组首元素的地址(两个例外):
int main()
{
int arr[] = {1,2,3};
printf("%pn",arr);
printf("%pn",&arr[0]);
printf("%dn",*arr);
return 0;
}
补充:1.sizeof(数组名),计算整个数组的大小,括号中的数组名表示整个数组;2.&数组名,取出的是数组的地址。&数组名,数组名表示整个数组。除此之外,所有的数组名都表示数组首元素的地址。
冒泡排序函数的正确设计当数组传参时,实际上是只把数组的首元素的地址传递了过去,即使在函数形参部分写成int arr[]表示的依然是int* arr。所以函数内部的sizeof(arr)结果是4,。函数正确的写法:
本人还有一篇关于数组应用的博客,为了更好地理解数组,大家可以看一看:https://blog.csdn.net/weixin_60720508/article/details/121223546



