浅谈数组
- 一维数组的创建和初始化。
- 数组的创建
数组是一组相同类型元素的集合。
数组的创建方式:
type_t arr_name [const_n];
//type_t 是指数组的元素类型
//const_n 是一个常量表达式,用来指定数组的大小
数组创建的实例:
//代码1 int arr1[10];
//代码2 int count = 10; int arr2[count];//数组时候可以正常创建?
//代码3 char arr3[10];
float arr4[1];
double arr5[20];
注:数组创建,在C99标准之前, [] 中要给一个常量才可以,不能使用变量。在C99标准支持了变常数组的概念。
目前vs2019不支持变常量
如果变常数组可以实现,也要注意变常数组是不能初始化的
-
- 数组的初始化
数组的初始化是指,在创建数组的同时给数组的内容一些合理初始值(初始化)。 看代码:
int arr1[10] = {1,2,3};//不完全初始化,其他几位自动补成0
int arr2[] = {1,2,3,4};
int arr3[5] = {1,2,3,4,5};
char arr4[3] = {'a',98, 'c'};
char arr5[] = {'a','b','c'};
char arr6[] = "abcdef";
值放多了会报错,告诉你初始化的值太多了
数组在创建的时候如果想不指定数组的确定的大小就得初始化。数组的元素个数根据初始化的内容来确定
但是对于下面的代码要区分,内存中如何分配。
char arr1[] = "abc";//a b c \0(4个字符)
char arr2[3] = {'a','b','c'};// a b c(三个字符)
这里如果写成
Char arr2[3]={‘a’,98,’c’};也一样,这里的98是ascc码值会自己转换成b(98);
如果这样设置 int arr[10];这时候这里的是十个数就是随机值;包括你赋值的数 int a;
这里的a也是随机值;如果一个全局变量不初始化,那么它不是随机值,它是0;
包括静态变量 static。
当我们在写代码的时候,c语言其实有三个区域,一个叫栈区(局部变量,形式参数),一个叫堆区,还有一个叫静态区(全局变量,静态变量);静态区上面数据的特点是,不初始化的话它的值默认为0,栈区上数据的特点是不初始化它的值的话就是随机值;
如果是 char arr【5】=“abc”//这里本来是abc\0。
1.3 一维数组的使用
对于数组的使用我们之前介绍了一个操作符: [ ] ,下标引用操作符。它其实就数组访问的操作符。
- 数组是使用下标来访问的,下标是从0开始。
Int arr[100]={1,2,3,4,5,6};
0 1 2 3 4 5
Printf(“%d”,arr[4]);
这时候就会出现5,因为这里用了下标引用操作符[ ],(有两个操作数arr 4)
我们可以通过下标访问数组
int main()
{
int arr[100] = {0};
for (int i = 0; i <= 99; i++)
{
arr[i] = i+1;
}
for (int i = 0; i <= 99; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
因为这里有100个元素,每个元素是整型所以结果是400
所以就是sizeof(arr)/sizeof(arr[0])可以得到数组里面的元素个数
-
- 一维数组在内存中的存储
通过地址我们可以发现,每两个数组之间的地址差4个字节,因为一个整型的大小是4个字节,同时我们发现一维数组在内存中连续存放的!随着数组下标的增长,地址是由低到高变化的,数组名是什么,是数组首元素的地址。
%p---打印地址(16进制)
%d---打印整数(10进制)
- 二维数组的创建和初始化
2.1 二维数组的创建
int arr[3][4];
char arr[3][5];
double arr[2][4];
二维数组不完全初始化的时候;
如果想在某一行放入自己想放的值可以这里设置
这样可以看出第一行是1,2;第二行是3,4在这一行未设置的部分自动转化成0了
不用行也行。
int main()
{
int arr[3][5] = { {1,2},{4,5},{5,6} };//把二维数组第一行看成一个数组,第二行跟第三行也分别看成一个数组
int i = 0; //总大小除以第一行的大小等于行数
for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
int j = 0;
for (j = 0; j < sizeof(arr[0]) / sizeof(arr[0][0]); j++)//第一行的大小除以第一行第一列的大小
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
打印数组每个元素的地址
我们发现二维数组这么多数之间还是差是个字节,说明他们都是连续的
可以把二维数组想象成几个一维数组
Arr【0】 arr【1】 arr【2】
访问任意一个数组
Arr【0】【j】 arr【1】【j】 arr【2】【j】
同时可以了解三维数组可以看成三个二维数组arr【3】【4】【5】;
- 数组越界
数组的下标是有范围限制的。 数组的下规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。 所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。 C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就 是正确的,所以程序员写代码时,最好自己做越界的检查。
二维数组的行和列也可能存在越界。
- 数组作为函数参数
往往我们在写代码的时候,会将数组作为参数传个函数,比如:我要实现一个冒泡排序(这里要讲算法 思想)函数 将一个整形数组排序。那我们将会这样使用该函数:
冒泡排序
数组中两个相邻的元素进行比较,如果不满足顺序就交换
例如我们将arr【】={9,8,77,6,5,4,3,2,1,0};进行升序排列
9 8 7 6 5 4 3 2 1 0 8 7 6 5 4 3 2 1 0 9
8 9 7 6 5 4 3 2 1 0 7 8 6 5 4 3 2 1 0 9
8 7 9 6 5 4 3 2 1 0 7 6 8 5 4 3 2 1 0 9
………………………… …………………………
8 7 6 5 4 3 2 1 0 9 7 6 5 4 3 2 1 0 8 9
这是一趟冒泡排序 这是第二趟冒泡排序
十个数要经过九趟冒牌排序
第一趟有九次比较,第二趟有八次比较,趟数跟元素个数有关系
void bubble_sort(int arr[])
{
int sz = sizeof(arr) / sizeof(arr[0]);
//趟数
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 = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
int main()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
//写一个冒泡排序
bubble_sort(arr);
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
我们按照逻辑设计完冒泡排序
发现没有进行排序
通过调试我们发现这里的sz=1;正常情况下sz=10;这里出现了bug
借此我们引出来一个新的问题
数组名是什么?
数组名就是数组首元素地址
有两个例外
printf("%p\n", sizeof(arr));数组名不是首元素地址,表示整个数组
&数组名,数组名不是首元素地址,数组名表示整个数组。取出的是整个数组的地址
三个值一样
给它们三个值加一
前两个加一的效果都是一样的,地址都差4
下面那个加了一个40
数组的每个元素都有地址
&arr+1从10以后开始
数组里面的2其实是arr+1或者&arr[0]+1
之后我们再看冒泡数组的问题
Main函数中的int arr【】={9,8,7,6,5,4,3,2,1,0}
Arr-表示首元素的地址其实就是&arr【0】的地址
本质上void bubble—sort(int arr【】)实际上是int*arr是一个指针
Int sz=sizeof(arr)/sizeof(arr【0】)
因为我们在传参的时候是传递的一个数组名,数组名其实是首元素地址,传过去是要有指针接收,他是一个整型指针
整形指针sizeof(arr)就是 4,sizeof(arr【0】)也是4,4/4=1;
这里的arr【】可以写成这样也可以写成*arr
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 = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
int main()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
//写一个冒泡排序
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;
}
应该将sz在外面求好作为一个参数才能解决问题