目录
一.? ?一维数组? ? ? ? ??? ?
? ? ? ? ? ? ?1.1? ?一维数组的创建
? ? ? ? ? ? ?1.2? ?一维数组的初始化
? ? ? ? ? ? ?1.3? ?一维数组在内存中的存储
二.? ?二维数组
? ? ? ? ? ? ?2.1? 二维数组的创建
? ? ? ? ? ? ?2.2? 二维数组的初始化
? ? ? ? ? ? ?2.3? 二维数组的使用
? ? ? ? ? ? ?2.4? 二维数组在内存中的存储
三.? ?数组越界
四.? ?数组作为函数参数
一.? ?一维数组? ? ? ? ??? ?
? ? ? ? ? ? ?1.1? ?一维数组的创建
数组是一组相同类型元素的集合。 数组的创建方式:
type_t arr_name [const_n];
//type_t 是指数组的元素类型
//const_n 是一个常量表达式,用来指定数组的大小
//arr_name即为数组名
//代码1
int arr1[10];
//代码2
int count = 10;
int arr2[count];//数组时候可以正常创建?
//代码3
char arr3[10];
float arr4[1];
double arr5[20];
再来看一些例子:
#include<stdio.h>
int main()
{
int a = 10;
int b = 20;
int c = 30;
int n = 10;
//int arr[n];//错误,不能这样写
int arr[5];
char ch[10];
}
注:数组创建,在C99标准之前, [] 中要给一个常量才可以,不能使用变量。在C99标准支持了变长数 组的概念。
? ? ? ? ? ? ?1.2? ?一维数组的初始化
数组的初始化是指,在创建数组的同时给数组的内容一些合理初始值(初始化)。
代码如下:
#include<stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//int arr[10] = { 1,2,3,4,5,6,7,8,9,10,11 };//错误
//越界,超过数组的最大范围值 10
int arr[10] = { 1,2,3 };//不完全初始化,剩余的元素默认初始化为0
int arr[10] = { 0 };
int arr[] = { 1,2,3 };
}
再看一个示例:
#include<stdio.h>
int main()
{
int arr[] = { 0 };//只有一个元素
int i = 0;
for (i = 0; i < 10; i++)
{
scanf("%d", &arr[i]);
}
return 0;
这里着重提到sizeof和strlen?
示例如下:
#include<stdio.h>
int main()
{
char arr1[] = { 'a','b','c' };
//arr1有3个元素,数组的大小是3个字节
printf("%d\n", sizeof(arr1)); //3
printf("%d\n", strlen(arr1)); //随即值
char arr2[] = "abc"; // a b c \0
//arr2有4个元素,数组的大小是4个字节
printf("%d\n", sizeof(arr2)); //4
printf("%d\n", strlen(arr2)); //3
return 0;
}
注:
strlen:? ? 是一个库函数,计算的是字符串的长度,并且只能针对字符串,关注的字符串中是否有\0,计算的是\0之前的字符个数 sizeof:? ?是一个操作符(运算符),sizeof是用来计算变量所占内存空间的大小,任何类型都可以使用,只关注空间大小,不在乎内存中是否有\0
数组在创建的时候如果想不指定数组的确定的大小就得初始化。数组的元素个数根据初始化的内容来确定。
一维数组的使用:
#include<stdio.h>
int main()
{
int arr[10] = { 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++)
{
scanf("%d", &arr[i]);
}
for (i = 0; i < sz;i++)
{
printf("%d ", arr[i]);
}
//printf("%d\n", arr[5]);//[]下标访问操作符
return 0;
}
数组元素的个数可以计算出来:
用所有数组的大小除以单个数组的大小:(sizeof(arr) / sizeof(arr[0])
? ? ? ? ? ? ?1.3? ?一维数组在内存中的存储
接下来我们探讨数组在内存中的存储。 看代码:
#include<stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//打印数组每个元素的地址
int i = 0;
for (i = 0; i < 10; i++)
{
printf("&arr[%d]=%p\n", i, &arr[i]);
}
return 0;
}
运行如下:
#include<stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int* p = &arr[0];
int i = 0;
for (i = 0; i < 10; i++)
{
//printf("&arr[%d]=%p\n", i, &arr[i]);
//printf("%p\n", p + i);//p+i,是数组arr[i]的地址
//printf("%p ----- %p\n", p + i, &arr[i]);
//printf("%d ", *(p + i));
}
return 0;
}
仔细观察输出的结果,我们知道,随着数组下标的增长,元素的地址,也在有规律的递增。 由此可以得出结论:数组在内存中是连续存放的。
二.? ?二维数组
? ? ? ? ? ? ?2.1? 二维数组的创建
#include<stdio.h>
int main()
{
int arr[3][4]; //三行四列
return 0;
}
? ? ? ? ? ? ?2.2? 二维数组的初始化
#include<stdio.h>
int main()
{
int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
int arr[3][4] = { 1,2,3,4,5,6,7 };//不完全初始化,剩余的补0
int arr[3][4] = { (1,2),(3,4),(5,6) };//第一行放1,2 第二行放3,4 第三行放5,6
return 0;
}
*二维数组的访问*
#include<stdio.h>
int main()
{
int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
//printf("%d", arr[2][3]);
int i = 0;
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 4; j++)
{
printf("%-2d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
访问过程就相当于检验初始化的具体内容,将其打印出来。
? ? ? ? ? ? ?2.3? 二维数组的使用
#include <stdio.h>
int main()
{
int arr[3][4] = {0};
int i = 0;
for(i=0; i<3; i++)
{
int j = 0;
for(j=0; j<4; j++)
{
arr[i][j] = i*4+j;
}
}
for(i=0; i<3; i++)
{
int j = 0;
for(j=0; j<4; j++)
{
printf("%d ", arr[i][j]);
}
}
return 0;
}
?
? ? ? ? ? ? ?2.4? 二维数组在内存中的存储
#include<stdio.h>
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("&arr[%d][%d]=%p\n", i, j, &arr[i][j]);
}
}
return 0;
}
?
三.? ?数组越界
数组的下标是有范围限制的。 数组的下规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。 所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。 C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就 是正确的, 所以程序员写代码时,最好自己做越界的检查。
#include<stdio.h>
int main()
{
int arr[10] = { 0 };
int i = 0;
for (i = 0; i < 10; i++)
{
for (i = 0; i < 10; i++)
{
arr[i] = i;
printf("%d ", arr[i]);
}
}
return 0;
}
?
#include<stdio.h>
int main()
{
int arr[10] = { 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;
}
四.? ?数组作为函数参数
//如:实现一个冒泡排序 //冒泡排序的思想: //两两相邻的元素进行比较,如果有可能的话需要交换。一趟冒泡排序能搞定一个数字,让当前待排序的数组中一个元素来到最终应该出现的位置上
#include<stdio.h>
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++) //一趟冒泡排序的过程
{
int tmp = 0;
if (arr[j] > arr[j + 1])
{
//交换
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
int main()
{
int arr[] = { 3,1,5,2,4,9,0,7,6,8 };
//设计一个函数对arr数组进行冒泡排序--冒泡排序的算法
int sz = sizeof(arr) / sizeof(arr[0]);
//数组传参
bubble_sort(arr,sz);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
?
补充:数组名
#include<stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5, };
printf("%p\n", arr); //arr是数组首元素的地址
printf("%p\n", &arr[0]); //数组首元素的地址
printf("%p\n", &arr);
printf("%p\n", arr + 1);
printf("%p\n", &arr[0] + 1);
printf("%p\n", &arr + 1);
printf("%d\n", sizeof(arr)); //20
//数组名是首元素的地址,但是有例外
//1:sizeof内部单独放一个数组名,,数组名表示整个数组,sizeof计算的是整个数组的大小,单位是字节
//2:&取地址数组名,数组名表示整个数组,取出的是整个数组的地址
}
?
? ?
?
|