C语言学习
文章目录
一、什么是数组?
二、一维数组的创建和初始化
1.数组的创建
2.数组的初始化
3.一维数组的使用
4.一维数组在内存中的存储
三、二维数组的创建和初始化
1.二维数组的创建
2.二维数组的初始化
3.二维数组的使用
4.二维数组在内存中的存储
三、数组越界
四、数组作为函数参数
1.数组名
2.冒泡排序
总结
- 数组:同一类型的变量——元素集中在一起,在内存上连续排列成一条直线。
- 元素类型可以是 int 类型,char 类型,也可以是 double 类型等。
数组的创建方式:
type_t arr_name [const_n];
- type_t 是指数组的元素类型。
- arr_name 是指数组名。
- const_n 是一个常量表达式,用来指定数组的大小。
数组创建实例:
代码示例:
#include
int main()
{
int arr1[10];
char arr2[15];
float arr3[6];
double arr4[20];
return 0;
}
数组的初始化就是在{ }中用逗号分隔并逐一赋给各元素的值。
代码示例:
#include
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 1,2,3 };
int arr3[] = { 1,2,3 };
char ch1[10] = { 'a','b','c' };
char ch2[10] = "abc";
char ch3[] = { 'a','b','c' };
char ch4[] = "abc";
return 0;
}
上述程序中数组被赋值的结果:
arr1数组对每个元素都进行了初始化赋值。
arr2数组进行了不完全初始化,剩余的元素默认初始化为0。
arr3数组中[ ]内元素个数可以省略,自动认为是3。
ch1数组和ch2数组中也进行了不完全初始化,虽然他们的赋值结果看起来一样,但本质上不同:
ch3数组和ch4数组的结果验证了不同。
[ ] ,下标引用操作符。它其实就数组访问的操作符。
代码示例:
#include
int main()
{
int arr[] = { 0,0,0,0,0 };
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);//计算数组的元素个数
for (i = 0; i < sz; i++)//输入元素的值
{
printf("arr[%d]:", i);
scanf("%d", &arr[i]);
}
for (i = 0; i < sz; i++)//输出元素的值
{
printf("arr[%d]=%d\n", i, arr[i]);
}
return 0;
}
运行结果:
arr[0]:1
arr[1]:2
arr[2]:3
arr[3]:4
arr[4]:5
arr[0]=1
arr[1]=2
arr[2]=3
arr[3]=4
arr[4]=5
- 数组是使用下标来访问的,下标是从0开始。
- 数组的大小可以通过计算得到。
代码示例:
#include
int main()
{
int arr[] = { 1,2,3,4,5 };
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
for (i = 0; i < sz; i++)
{
printf("arr[%d]:%p\n", i, &arr[i]);
}
return 0;
}
运行结果:
arr[0]:00000052B858F578
arr[1]:00000052B858F57C
arr[2]:00000052B858F580
arr[3]:00000052B858F584
arr[4]:00000052B858F588
调试数组内存图:
结论: 数组在内存中是连续存放的。
二维数组创建实例:
int arr1[3][4];
char arr2[3][5];
double arr3[3][6];
代码示例:
#include
int main()
{
int arr1[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
int arr2[3][4] = { 1,2,3,4,5,6,7,8,9 };
int arr3[3][4] = { {1,2},{3,4},{5,6} };
int arr4[][4] = { 1,2,3,4,5,6,7,8,9 };
int arr5[][4] = { {1,2},{3,4},{5,6} };
return 0;
}
二维数组如果有初始化,行可以省略,列不能省略。
上述程序中二维数组被赋值的结果:
二维数组的使用是通过下标的方式。
二维数组中元素的输入和输出
代码示例:
#include
int main()
{
int arr[3][4] = { 0 };
int i = 0;
int j = 0;
printf("输入数组元素:\n");
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
scanf("%d", &arr[i][j]);
}
}
printf("输出数组元素:\n");
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
运行结果:
输入数组元素:
1 2 3 4 5 6 7 8 9 10 11 12
输出数组元素:
1 2 3 4
5 6 7 8
9 10 11 12
二维数组其实可以看做是元素为一维数组的数组,如上述代码中的二维数组arr:他的第一行元素:1 2 3 4相当于一个一维数组,第二行和第三行也是一样。那么数组的三行都是一维数,它们三个具有统一性,可以作为元素,则可以把他们当作三个元素。所以arr数组就是有三个元素的数组,每个元素都是一维数组。
代码示例:
#include
int main()
{
int arr[3][4] = { 0 };
int i = 0;
int j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
printf("arr[%d][%d]:%p\n", i, j, &arr[i][j]);
}
printf("\n");
}
return 0;
}
运行结果:
arr[0][0]:0000001D6F6FF588
arr[0][1]:0000001D6F6FF58C
arr[0][2]:0000001D6F6FF590
arr[0][3]:0000001D6F6FF594
arr[1][0]:0000001D6F6FF598
arr[1][1]:0000001D6F6FF59C
arr[1][2]:0000001D6F6FF5A0
arr[1][3]:0000001D6F6FF5A4
arr[2][0]:0000001D6F6FF5A8
arr[2][1]:0000001D6F6FF5AC
arr[2][2]:0000001D6F6FF5B0
arr[2][3]:0000001D6F6FF5B4
二维数组在内存中也是连续存储的。
- 数组的下标是有范围限制的。
- 数组的下规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。
- 所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。
- C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的。所以程序员写代码时,最好自己检查数组是否越界。
数组传参的时候形参有两种写法:
- 数组
- 指针
形参用数组的写法传递时,传参可以用数组名传递,传递过去的数组名表示什么?
- 数组名可以表示首元素地址
但是以下两情况例外:
- sizeof(数组名):这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节。
- &数组名:这里这里的数组名表示整个数组,取出的是整个数组的地址。
一维数组关于数组名的代码示例:
#include
int main()
{
int arr[10] = { 0 };
printf("数组名:\n");
printf("%p\n", arr);
printf("%p\n", arr + 1);
printf("首元素地址:\n");
printf("%p\n", &arr[0]);
printf("%p\n", &arr[0] + 1);
printf("&数组名:\n");
printf("%p\n", &arr);
printf("%p\n", &arr + 1);
printf("sizeof(数组名)内存大小:\n");
int n = sizeof(arr);
printf("%d\n", n);
return 0;
}
运行结果:
数组名:
000000BFF5BCFC18
000000BFF5BCFC1C
首元素地址:
000000BFF5BCFC18
000000BFF5BCFC1C
&数组名:
000000BFF5BCFC18
000000BFF5BCFC40
sizeof(数组名)内存大小:
40
二维数组关于数组名的代码示例:
#include
int main()
{
int arr[3][4] = { 0 };
printf("sizeof(数组名)内存大小:\n");
int sz = sizeof(arr);
printf("%d\n", sz);
printf("\n");
printf("数组名地址:\n");
printf("%p\n", arr);
printf("%p\n", arr + 1);
printf("\n");
printf("二维数组行和列的计算:\n");
printf("二维数组行:\n");
printf("%d\n", sizeof(arr) / sizeof(arr[0]));
printf("二维数组列:\n");
printf("%d\n", sizeof(arr[0]) / sizeof(arr[0][0]));
return 0;
}
运行结果:
sizeof(数组名)内存大小:
48
数组名地址:
00000028E451FBF8
00000028E451FC08
二维数组行和列的计算:
二维数组行:
3
二维数组列:
4
二维数组数组名也是首元素的地址
冒泡排序的核心思想:两个相邻的元素进行比较。
一趟冒泡排序让一个数据来到他最终应该出现的位置上。
设计一个函数,把数组元素排为升序。
代码示例:
#include
//void bubble_sort(int* arr, int sz)//形参是指针的形式
void bubble_sort(int arr[], int sz)//形参是数组的形式
{
int i = 0;
for (i = 0; i < sz - 1; i++)//冒泡排序的趟数是数组元素个数减一
{
int j = 0;
for (j = 0; j < sz - 1 - i; j++)//一趟冒泡排序
{
if (arr[j] > arr[j + 1])//相邻两元素比较,交换
{
int tmp = 0;
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
int main()
{
int arr[] = { 9,8,7,6,5,4,3,2,1 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr,sz);//冒泡排列算法,把数组排成升序
int i = 0;
for (i = 0; i < sz; i++)//排序好数组打印
{
printf("%d ", arr[i]);
}
return 0;
}
运行结果:
1 2 3 4 5 6 7 8 9
以上就是今天要讲的内容,本文介绍了一维数组和二维数组还有一些数组的运用。