数组
-数组定义
能批量定义一些变量,这些变量在内存空间是连续的
-数组的创建
type_t arr_name [const_n]
type_t 是数组的元素类型
const_n 是一个常量表达式,用来定义数组的大小
代码演示:
//代码1
int arr1[10];
char arr2[3];
double arr3[5];
//注意:代码2
int count=10;
int arr4[count];
//数组无法建立,在数组创建的时候,"[]"中必须要给一个常量,不能使用变量
//除了使用字面字面常量可以创建数组,也可以使用一些特殊的常量来创建数组
//代码3
#define n 10
int arr5[n];
//define定义的表示常量可以用于数组的创建
//代码4
enum n
{
n=10,
};
int arr6[n];
//枚举常量也可以用于数组的创建
//当然并不是所有的常量都可以创建变量
//代码5
const int n=10;
int arr7[n];
//在C语言中,不承认const作用的变量n为常量
-数组的初始化
在创建数组的同时给数组的内容一些合理初始值
代码演示:
int arr1[10]={1,2,3};//前三个数为1,2,3,后7个数全为0
int arr2[]={1,2,3};
//"[]"中无常量,但是数组的数据有三个,所以默认"[]"中的常量为3
char arr5[]={'a','b','c'};
char arr6[]="abc";
//注意:要特别区分上述的两个代码,虽然都是字符数组,但是arr6是一个保存了一个字符
串字符数组,它占4个字节,因为还有一个'\0',但是arr5则只占3个字节
-数组的具体使用
代码演示:
#include <stdio.h>
int main()
{
int arr[10] = {0};//数组的不完全初始化
//计算数组的元素个数
int sz = sizeof(arr)/sizeof(arr[0]);
//对数组内容赋值,数组是使用下标来访问的,下标从0开始。所以:
int i = 0;//做下标
for(i=0; i<10; i++)
{
arr[i] = i;
}
//输出数组的内容
for(i=0; i<10; ++i)
{
printf("%d ", arr[i]);
}
}
结果为:0,1,2,3,4,5,6,7,8,9
注意1:int arr[10];和arr[10]是不同的,第一个是数组的定义,第二个是数组的访问,访问下标为10的数组中的数据,而数组的下标是从0开始的,所以最大的下标为9
注意2:在进行for循环的时候因为i是从0开始循环,所以的大小必须要小于10,如果等于10,那么数组就会产生第11个数据,而数组在定义的时候只有10个数据,此时数组就会越界,产生未定义行为
-数组大小的计算
数组的大小可以利用sizeof()来计算
代码演示:
#include <stdio.h>
int main()
{
int arr[10] = {0};
int size=sizeof(arr)/sizeof(arr[0]);
//sizeof(arr)计算的是整个数组所占的字节数
//sizeof(arr[0])计算的是下标为0的数据所占的字节数
//二者相除计算出数组的大小
printf("size=%d",size);
return 0;
}
结果为:size10;
注意:sizeof是在编译过程中运算的,所以会出现这一现象
代码演示:
#include <stdio.h>
int main()
{
int arr[5] = {5,4,3,2,1};
printf("arr[10]=%d\n",arr[10]);
return 0;
}
结果为:
很明显数组下标访问越界,此时是未定义行为,但是一定要注意数组下标越界并不是都会产生未定义行为
代码演示:
#include <stdio.h>
int main()
{
int arr[5] = {5,4,3,2,1};
printf("byte=%d\n",sizeof(arr[10]));
return 0;
}
结果为:
这里不是未定义行为,为什么明明数组下标越界访问答案还是对的,是4个字节?
因为未定义行为是在运行过程中访问非法内存,而sizeof的计算方法,我们上面已经提到是在编译过程中进行的运算,源程序在运行过程中会先编译,所以等于说是在实际运行之前已经计算好了数组中数据的所占的字节数,在运行时,不会再去访问arr[10]这个越界的非法内存,所以就不会出现未定义行为
-数组在内存中的存储
代码演示:
#include <stdio.h>
int main()
{
int arr[10] = {0};
int i = 0;
for(i=0; i<sizeof(arr)/sizeof(arr[0]); ++i)
{
printf("&arr[%d] = %p\n", i, &arr[i]);
}
return 0;
}
结果为:
可以看出数组在内存中是连续存放的,并且是从低地址开始存放
-数组作为函数参数
数组作为函数参数的时候会隐式转换为指针指向数组的首元素
代码演示:
#include<stdio.h>
void BubbleSort(int arr[])
{
int size=sizeof(arr)/sizeof(arr[0])
printf("size=%d\n",size);
}
int main()
{
int arr[]={5,4,7,2,1,0};
Founc(arr);
}
结果为:
为什么这里size会等于1呢,不应该是6吗?
因为在数组作为函数参数的时候会隐式转换为指针指向数组的首元素,那么此时arr就成为了一个指针,指针所占的字节数在32位系统中为4,所以sizeof(arr)=4,再除以4就是1
如果你想避免这种情况,可以在主函数中现将size计算出来,然后也和数组一起传入到函数中,做函数的参数
代码演示:
#include<stdio.h>
void BubbleSort(int arr[],size)
{
printf("size=%d\n",size);
}
int main()
{
int arr[]={5,4,7,2,1,0};
int size=sizeof(arr)/sizeof(arr[0])
Founc(arr,size);
}
结果为:
在数组传参的时候要时刻注意着数组此时隐式转换成为了指针
-二维数组
二维数组其实是一种特殊的一维数组,相当于一位数组中的每个数据是一个数组
数组的建立:
int arr[3][4];
char arr[4][4];
数组的初始化:
int arr[3][2]=
{
{1,2},
{0,5},
{4,3}
}
//可以看成是一个数组中有3个元素,每个元素又是一个数组,每个数组中又有2个元素
int arr[][4]={1,2};
//可以省略第一个"[]"中的数字,但不能省略第二个"[]"中的数字
注意:二维数组的存储和一维数组的存储效果是一样的,都是连续的,并且当二维数组作为函数的参数的时候他也会因式转换成为指针,但不同与一位数组的是他会转换为数组指针