数组的解析
在程序设计中,为了处理方便,把具有相同类型的若干变量按有序的形式组织起来。这些按序排列的同类型数据元素的集合称为数组。
数组中的所有元素必须是相同的数据类型。
数组的几点说明
1、在计算机内存中,同一数组的所有元素按下标顺序依次存放在相邻的存储单元中,因此数组占据的内存空间大小可由数组长度和数组类型计算出来。
2、数组名是数组的唯一标识符
3、数组元素用数组名和元素下标表示。
一维数组
//数组创建
int a[10]; //定义整型数组a,有10个元素
float b[10]; //定义浮点型数组b,有10个元素
char c[20]; //定义字符数组c,有20个元素
//数组初始化
int a[10] = { 1, 2, 3, 4, 5, 6 };
int b[] = { 1, 2, 3 };
char c[3] = { 'a', 'b', 'c' };
char d[] = "abcdef";
注:数组创建时[ ]中必须为常量,不能使用变量。
数组在创建时如果不想指定数组的大小,就必须得初始化。数组的元素个根据初始化的内容来确定。
对于下面的代码,要区分内存中是如何分配的。
数组使用时是通过下标来访问的,下标从0开始。
int main()
{
int arr[5] = { 0 };
int i = 0;
for (i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
{
printf("&arr[%d] = %p\n", i, &arr[i]);
}
return 0;
}
我们可以看出随着下标的增长,地址也在递增。
由此,我们可以知道,一维数组在内存中是连续存放的。
int main()
{
int arr[] = { 1, 2, 3, 4, 5};
printf("%p\n", arr);
printf("%d\n", *arr);
return 0;
}
对这块地址解引用我们得到了第一个元素的值,可见,数组的数组名就是数组首元素的地址。
二维数组
//数组创建
int arr1[3][4];
char arr2[3][5];
double arr3[2][4];
//数组初始化
int arr1[3][4] = { 1, 2, 3, 4 };
int arr2[3][4] = { { 1, 2 }, { 4, 5 } };
int arr3[][4] = { { 2, 3 }, { 4, 5 } };
二维数组也是通过下标来访问其中的元素的。
int main()
{
int arr[2][3];
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
printf("&arr[%d][%d] = %p\n", i, j, &arr[i][j]);
}
}
return 0;
}
可以看出,在C语言中,二维数组是按行存储的,且地址是连续的。
看下面的代码。
数组的运算
数组名代表整个数组的大小只有两种情况:
① 数组名单独放在sizeof()中
② &数组名
整型一维数组
//一维数组
int a[] = { 1, 2, 3, 4 };
printf("%d\n", sizeof(a)); //16 整个数组的大小
printf("%d\n", sizeof(a + 0));//4 数组名降级为数组首元素地址
printf("%d\n", sizeof(*a));//4 数组首元素
printf("%d\n", sizeof(a + 1));//4 数组第二个元素的地址
printf("%d\n", sizeof(a[1]));//4 数组第二个元素
printf("%d\n", sizeof(&a));//4 数组的地址
printf("%d\n", sizeof(&a + 1));//4 跳过整个数组,指向数组后面的元素
printf("%d\n", sizeof(&a[0]));//4 数组第一个元素的地址
printf("%d\n", sizeof(&a[0] + 1));//4 数组第二个元素的地址
printf("%d\n", sizeof(*&a));//16 &a为数组的地址,解引用取出数组中的所有元素
字符数组
//字符数组
char arr[] = { 'a', 'b', 'c', 'd', 'e', 'f' };
printf("%d\n", sizeof(arr));//6 字符数组的大小
printf("%d\n", sizeof(arr + 0));//4 数组名降级为数组首元素地址
printf("%d\n", sizeof(*arr));//1 数组首元素
printf("%d\n", sizeof(arr[1]));//1 数组第二个元素
printf("%d\n", sizeof(&arr));//4 数组的地址
printf("%d\n", sizeof(&arr + 1));//4 跳过整个数组,指向数组后面的那个元素
printf("%d\n", sizeof(&arr[0] + 1));//4 第二个元素的地址
//strlen()参数部分需要一个地址
printf("%d\n", strlen(arr));//随机值
printf("%d\n", strlen(arr + 0));//随机值
//printf("%d\n", strlen(*arr));错误
//printf("%d\n", strlen(arr[1]));错误
printf("%d\n", strlen(&arr));//随机值
printf("%d\n", strlen(&arr + 1));//随机值
printf("%d\n", strlen(&arr[0] + 1));//随机值
char *p = "abcdef";
printf("%d\n", sizeof(p));//4 字符a的地址
printf("%d\n", sizeof(p + 1));//4 字符b的地址
printf("%d\n", sizeof(*p));//1 字符指针解引用
printf("%d\n", sizeof(p[0]));//1 字符a
printf("%d\n", sizeof(&p));//4 p的地址
printf("%d\n", sizeof(&p + 1));//4 地址
printf("%d\n", sizeof(&p[0] + 1));//4 b的地址
printf("%d\n", strlen(p));//6 从a开始遇到'\0'结束
printf("%d\n", strlen(p + 1));//5 从b开始
//printf("%d\n", strlen(*p));错误
//printf("%d\n", strlen(p[0]));错误
printf("%d\n", strlen(&p));//随机值
printf("%d\n", strlen(&p + 1));//随机值
printf("%d\n", strlen(&p[0] + 1));//5 从b开始
二维数组
//二维数组
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));//48 整个数组的大小
printf("%d\n", sizeof(a[0][0]));//4 第一个元素
printf("%d\n", sizeof(a[0]));//16 第一行
printf("%d\n", sizeof(a[0] + 1));//4 第一行的第二个元素
printf("%d\n", sizeof(a + 1));//4 第二行的地址
printf("%d\n", sizeof(&a[0] + 1));//4 第二行的地址
printf("%d\n", sizeof(*a));//16 第一行地址解引用,第一行的所有元素
printf("%d\n", sizeof(a[3]));//16 sizeof内部不参与表达式运算