数组是一组相同类型元素的集合。 数组的创建方式:
类型 数组名 [](数组大小,可以空着,空着的话空间就根据你后面赋值多少定。)
举个例子
nt arr[];
这就是创建一个数组,数组名为arr,数组类型是int。
这里必须要注意的是,数组名后括号里面不可以用变量,比如:
int count = 10;
int arr1[count];
这种是不合规范的,使用时应该尽量避免。
下面开看一下数组的使用。
#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;
}
这里,我定义了一个数组,数组名是arr,有10个元素,每个元素是int型,然后我定义一个i,这里要说明一下,数组是根据下标来访问的。
比如你数组是:1 2 3 4 5 6 7 8 9 10
数组的下标是:0 1 2 3 4 5 6 7 8 9
数组的下标是从0开始,也就是说访问数组的第一个元素是找下标为0的元素。
这里for循环,arr[i],i = 0;从数组的第一个元素开始找,找下标为i的元素,并把i赋值。
这样赋值完就是0 1 2 3 4 5 6 7 8 9
之后打印出来。
数组的大小可以通过函数sizeof求,使用如下:
int sz = sizeof(arr)/sizeof(arr[0]);
用整个数组大小除以其中一个元素的大小。
数组的储存
看下面一串代码:
#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;
}
结果如下:
可以看出来,数组在内存中是连续存放的 。
二维数组
我们知道char arr[] = {0}; 可以创建一个数组,[]类是数组的元素,我们看到这样创建出来的数组就好像一条直线,想象一下这是四边形的长,我们可以不可以在[]后面再加一个[]? 就好像给它一个宽?
是可以的,类似这样的数组,我们称之为二维数组。
int arr[3][4] = {1,2,3,4};
int arr[3][4] = {{1,2},{4,5}};
int arr[][4] = {{2,3},{4,5}};
这里是创建的示范,注意,创建时第一个是行,第二个是列,以 arr[3][4] 举例,这里[3]可以省略,试想一下,当你有八个元素,放到4列里面,是不是一行塞不下?所以就会放到下一行去。
但如果你没有列,只有行的话,那一行可以放多少元素呢?无限放的话还要下一行干什么呢?
二维数组的储存
#include <stdio.h>
int main()
{
int arr[3][4];
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,就是数组越界访问了,超出了数组合法空间的访问。
#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("%d\n", arr[i]);
}
return 0;
}
以这个举例子,数组10个元素,每个元素都有对应的下标,又因为第一个元素的下标是0,所以最后一个元素的下标是10-1 = 9,但我打印的时候把下标为10的元素打印出来,那这里就是越界。
数组作为函数参数
往往我们在写代码的时候,会将数组作为参数传个函数,比如:我要实现一个冒泡排序(住1),将一串顺序错乱的整数排列成有序,我该如何实现?
#include <stdio.h>
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-i-1; j++)
{
if(arr[j] > arr[j+1])
{
int tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
}
int main()
{
int arr[] = {3,1,7,5,8,9,0,2,4,6};
bubble_sort(arr);
for(i=0; i<sizeof(arr)/sizeof(arr[0]); i++)
{
printf("%d ", arr[i]);
}
return 0;
}
以这个举例,我们希望得到的是:0 1 2 3 4 5 6 7 8 9 ,但实际上,我们得到的是:
结果出乎我们意料之外,为什么结果不是我们所想的?
这里我们一步一步调试,看到下图:
sz传过去了,但是为什么算出来的是1?
数组名是什么?
#include <stdio.h>
int main()
{
int arr[10] = {1,2,3,4,5};
printf("%p\n", arr);
printf("%p\n", &arr[0]);
return 0;
}
我们写出如上代码,看看数组第一个元素的地址,和取出数组地址对比:
可以看到两个地址是一样的,我们是不是可以理解为,数组名是首元素地址?
但如果数组名是首元素地址,那我们计算:
int arr[10] = {0};
printf("%d\n", sizeof(arr));
为什么结果是40?
这里说两个例外:
1. sizeof(数组名),计算整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数 组。 2. &数组名,取出的是数组的地址。&数组名,数组名表示整个数组。
除此之外,数组名表示的是首元素的地址。
所以我们不应该在函数内部计算数组大小,那我们将数组大小在主函数里面算出来再传过去,结果能如我们所愿吗?
#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-i-1; j++)
{
if(arr[j] > arr[j+1])
{
int tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
}
int main()
{
int arr[] = {3,1,7,5,8,9,0,2,4,6};
int sz = sizeof(arr)/sizeof(arr[0]);
bubble_sort(arr,sz);
for(i=0; i<sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
当然,这一次数组就有序排列了。
数组就讲到这里。