首先,我们要知道数组是相同类型元素的集合。
type_t arr_name [const_n];
//type_t 是指数组的元素类型
//const_n 是一个常量表达式,用来指定数组的大小
这是在visual studio 2022中的情况:
在visual studio 2022中我们看见它是不行的,实际上数组[变量]这种语法是c99标准中的,它叫变长数组。很明显,visual studio 2022不支持c99版本。
在支持c99标准的编译器下是可以运行的,并不会报错。
int arr[2+3]//这种语法是对的,[]中可以是表达式
char arr1[2 + 3];
int arr2[2 + 3];
int arr3[3 + 2];//加法支持交换律
float arr4[4 + 3];
double arr5[5 + 3];
//以上都是正确的,不用质疑
注意:数组创建,在C99标准之前, [] 中要给一个常量才可以,不能使用变量。在C99标准支持了变长数组的概念,数组的大小可以使用变量指定,但是数组不能初始化
首先了解初始化和赋值的意思:
int a = 0;//这叫初始化
int n;
n = 20;//这叫赋值
初始化是创建变量的同时给定一个数值。
赋值是创建变量之后对这个变量给定一个数值
重点放在初始化是同时进行,赋值是一前一后进行
这种写法是可以的。
arr数组中存放的是123,这里没有给定空间大小,数组就自动根据元素个数给定这个数组大小。这个数组的空间大小是12。
这种写法是没有问题的,这个叫做不完全初始化。
这个数组中存放的是1234500000,说明了初始化不完全,编译器会自动给其初始化为0,这里的数组空间大小是40,原因是我们规定了数组大小。
这里我们发现,arr1中有四个元素,arr2中有三个元素,说明arr1的空间大小是4,arr2的空间大小是3。
理解了这点再来看看char arr3[10] = "abc"和char arr4[10] = {‘a’,‘b’,‘c’}的区别:
这里我们看到的是一样的,其实并不是,上面我们已经验证了char arr1[] = “abc”,arr1中包含的是a,b,c,\0,arr2中包含a,b,c,这里虽然arr3和arr4看起来一样,但是不同,arr3中其实是a,b,c,\0,0,0,0,0,0,0,arr4中其实是a,b,c,0,0,0,0,0,0,0,这就能解释为什么不一样的原因了。
对于数组的使用我们知道[]是一个下标引用操作符,其实就是数组访问的操作符。我们之前提到一个交换律的概念,如:2+3可以写成3+2,一个双目操作符的两个操作数是可以交换的,数组中的两个操作数在某些场景中也是可以交换的,如:
#include
int main()
{
int arr[] = { 1,2,3,4,5 };
int i = 0;
for (i = 0; i < 5; i++)
{
printf("%d ", i[arr]);
//printf("%d ",arr[i]);
}
return 0;
}
总结:
1.数组是使用下标来访问的,下标是从0开始的。
2.数组的大小可以通过计算得到
int arr[10];
int sz = sizeof(arr)/sizeof(arr[0]);
还是先看现象再看实质;
通过这段代码我们发现地址都是隔4个字节的大小,说明一维数组在内存中是连续存放的。随着数组下标的增长,地址也是由低地址到高地址变化。
int arr[3][4];//三行四列的数组
char arr[3][4];
double arr[2][4];
前一个[]中的数字代表行数,后一个[]中的数字代表列数。
解释:这个数组是个三行四列的数组,所以第一行存储1234,其他两行被默认初始化为0。
如图,发现{1,2}和{4,5}相当于一维数组,列数不够在其后默认初始化为0。
int arr[][] = {0};//错误
int arr[][2] = {0};//正确
int arr[2][] = {0};//错误
int arr[2][2] = {0};//正确
arr[][]和arr[2][]都会报错,说明arr缺少下标。
注意:二维数组如果初始化,行可以省略,列不能省略。
二维数组的使用也是通过下标的方式。
#include
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("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
数组的下标是有范围限制的。
数组的下规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就
是正确的,所以程序员写代码时,最好自己做越界的检查
通过代码看现象:
这是一维数组中的越界访问,没有下标为10的这个元素,所以打印出来的不知道是那块内存的数据。
就像当于这样子;
这里以冒泡排序为例子
冒泡排序是什么?
听到冒泡就很容易联想到泡泡,在水中有水底浮上水面上,慢慢变大。这里的冒泡排序就是由小到大升序排列的意思
具体怎么实现?
核心就是两两相邻的元素进行比较
思路:
完成的趟数=总元素个数-1,完成一趟的次数=完成的趟数-i(i=0~(完成的趟数-1))
代码实现:
//错误的代码
#include
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 temp = 0;
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int main()
{
//给出几个数字,以9 8 7 6 5 4 3 2 1 0为例
int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
//实现一个函数进行排序
bubble_sort(arr);
//打印
int z = 0;
for (z = 0; z < 10; z++)
{
printf("%d ", arr[z]);
}
return 0;
}
那么哪里错了呢?
int sz = sizeof(arr)/sizeof(arr[0]);这里错了,不应该放在函数中,因为数组传参传的是首元素地址(也就是一个指针),在x86平台下,sizeof(arr)=4,在x64平台下sizeof(arr)=8,所以sz=1,只是交换了一次,所以打印出8 9 7 6 5 4 3 2 1 0的结果。
下面是正确的代码展示:
//正确的代码
#include
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 temp = 0;
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int main()
{
//给出几个数字,以9 8 7 6 5 4 3 2 1 0为例
int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
//实现一个函数进行排序
bubble_sort(arr,sz);
//打印
int z = 0;
for (z = 0; z < 10; z++)
{
printf("%d ", arr[z]);
}
return 0;
}
一般请况下数组名是首元素地址。
这么说你肯定不理解,看图:
一下子你就明白了,首元素就是首元素地址这个关系。
这个还不能说明什么的话,那就再看一个例子:
用数组名指向的元素和每个元素取到的地址相同。
我们说数组名是个指针,下面来说明一下:
1.sizeof(数组名),这里的数组名是整个数组,计算的是整个数组的大小,单位是字节
2.&数组名中,这个数组名是整个数组的大小,取出整个数组的地址
证明:
见博主这么努力给博主关注关注,点点赞,支持支持吧! 看博主那么可怜!
写的还不错嘛,
哈哈开个玩笑呐,还望诸位多多支持,指点一二,感谢感谢!