一维数组
- 数组的创建
数组是一组相同类型元素的集合。
创建方式:
type_t arr_name [const_n];
//type_t 是指数组的元素类型
//const_n 是一个常量表达式,用来指定数组的大小
例:
int arr1[10];
char arr3[10];
float arr4[1];
double arr5[20];
int count = 10;
int arr2[count]; //此处无法正常创建,编译会报错
也就是说:
在创建数组时,[ ]中要给一个常量才可以,而不能使用变量。
2.数组的初始化
数组的初始化是指在创建数组的同时给数组的内容一些合理的初始值(初始化)。
例:
int arr1[10] = { 1, 2, 3 }; //数组前三个元素为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[] = "abcde";
char arr2[5] = {'a','b','c','d','e'};
char *p = "abcde";
如图:
3.一维数组的使用
- 数组是通过下标来访问的。
- 数组的大小可以通过计算得到。
- [ ]:解引用操作符(数组访问的操作符)。
- 例:
#include<stdio.h>
int mian()
{
int arr[10] = { 0 }; //数组的不完全初始化。
//对数组内容赋值,数组是使用下标来访问的,下标从0开始
int i = 0; //做下标
for (i = 0; i<10; i++)
{
arr[i] = i;
}
//输出数组的内容
for (i = 0; i<10; ++i)
{
printf("arr[%d] = %d;\n ",i, arr[i]);
}
printf("\n");
//数组的大小通过计算可以得到
int sz = sizeof(arr) / sizeof(arr[0]);
printf("size = %d\n", sz);
return 0;
}
结果如下:
4.数组在内存中的存储
- 通过一段代码查看数组在内存中的存储:
#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]);
}
}
结果如下:
观察结果可发现:随着下表的增长,元素的地址也在有规律的递增。
- 结论:
数组在内存中是连续存放的。
5.一维数组的指针访问
- 首先,通过一段类似于之前的代码,对输出的地址进行解引用。
#include<stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6 };
printf("%p\n", arr);
//对地址进行解引用
printf("%d\n", *arr);
return 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]);
printf("%p\n", arr + i);
return 0;
}
输出结果为:
也就是说,也可以通过指针来访问数组。
例:
#include<stdio.h>
int main()
{
int arr[10] = { 0 };
int i = 0;
int *p_arr = arr;
for (i = 0; i<sizeof(arr) / sizeof(arr[0]); ++i)
{
*(p_arr + i) = i;
}
for (i = 0; i<sizeof(arr) / sizeof(arr[0]); ++i)
{
printf("%d\n", *(p_arr + i));
}
return 0;
}
输出结果为:
二维数组
- 二维数组的创建及初始化
//数组的创建
int arr[2][3];int arr[3][4];
char arr[3][5];
double arr[2][4];
//数组的初始化
int arr[3][4] = {1,2,3,4};
int arr[3][4] = {{1,2},{4,5}};
int arr[][4] = {{2,3},{4,5}};
2.二维数组的使用及存储
- 首先先看一段代码:
#include<stdio.h>
int main()
{
int arr[3][4] = { 0 };
int i = 0;
for (i = 0; i<3; i++)
{
int j = 0;
for (j = 0; j<4; j++)
{
arr[i][j] = i * 4 + j;
printf("arr[%d][%d] = %d \n",i, j, arr[i][j]);
printf("&arr[%d][%d] = %p\n", i, j, &arr[i][j]);
}
}
return 0;
}
输出结果为:
由结果发现:
- 二维数组的使用也是通过下标访问的。
- 二维数组在内存中也是连续存储的。
如图所示:
3.二维数组的指针访问例:
#include<stdio.h>
int main()
{
int arr[3][4] = { 0 };
int *p = &arr[0][0];
int i = 0;
for (i = 0; i<3 * 4; i++)
{
p[i] = i;
}
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 4; j++)
{
printf("%d ", arr[i][j]);
}
}
return 0;
}
结果为:
一些关于数组的运算
注:以下程序均为在32位平台下运行。
//一维数组
int a[] = { 1, 2, 3, 4 };
printf("%d\n", sizeof(a)); //16 (数组名代表整个数组)
printf("%d\n", sizeof(a + 0)); //4 (sizeof(a[0]))
printf("%d\n", sizeof(*a)); //4
printf("%d\n", sizeof(a + 1)); //4 (sizeof(a[1]))
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
//字符数组
char arr[] = { 'a', 'b', 'c', 'd', 'e', 'f','g' ,'h'};
printf("%d\n", sizeof(arr)); //8
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
printf("%d\n", strlen(arr)); //随机值 (strlen遇到'\0'结束)
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 (p是指针)
printf("%d\n", sizeof(p + 1)); //4
printf("%d\n", sizeof(*p)); //1
printf("%d\n", sizeof(p[0])); //1
printf("%d\n", sizeof(&p)); //4
printf("%d\n", sizeof(&p + 1)); //4
printf("%d\n", sizeof(&p[0] + 1)); //4
printf("%d\n", strlen(p)); //6 (sizeof("abcdef") 的值为7)
printf("%d\n", strlen(p + 1)); //5
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
//二维数组
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 (sizeof(a[0][1]))
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(数组名),这里的数组名表示整个数组。
&数组名,这里的数组名表示整个数组。
除此之外,都表示首元素地址。