数组
基本概念
数组是由相同类型的多个元素组成的一种复合型数据类型
在程序中同时定义多个相同类型的变量时,可以使用数组
逻辑:定义数组时系统会生成一片连续的内存空间
格式: 类型说明 数组名[整形常量表达式];
#include <stdio.h>
int main(int argc, char const *argv[])
{
char a[5];
printf("a size is %d\n",sizeof(a));// 输出a的地址,数组名相当于这个数组的首元素地址
printf("a addr : %p\n",a);
// 输出a的首元素地址
printf("a[0] addr : %p\n",&a[0]);
printf("a[1] addr : %p\n",&a[1]);
// 数组的下标地址与首地址的偏移量有关,与数组的大小无关
// 比如,int a[3] = a的基地址+偏移量2
printf("a[2] addr : %p,%p,%p\n",&a[2],a+2,&a[0]+2);
// 输出变量b的地址
int b = 10;
printf("%p\n",&b);
return 0;
}
-
整型常量表达式:指定数组元素的个数
int a[5];//定义一个数组a,该数组一个由五个元素,每个元素都是int类型
int size = 4;
int array[size];//变长数组,如果式局部变量则正确,全局变量编译出错
-
语法释义:
-
a是数组名,即这片连续内存的名称
-
[5]代表这片连续内存总共分成5个相等的格子,每个格子称为数组的元素
-
int代表每个元素的类型,可以是任意基本类型,也可以是组合类型,甚至可以是数组
-
数组中所有元素的类型都是一致
-
数组申请的空间是连续的,从低地址到高地址依次连续存放数组中的每个元素
-
#include <stdio.h>
int main(int argc, char const *argv[])
{
// 申请5块连续的空间,将a称为数组
int a[5];
// 将这5块空间逐一赋值,注意,数组下标从0开始
a[0] = 1;
a[1] = 20;
a[2] = 30;
a[3] = 40;
a[4] = 50;
//a[5] = 60; // 越界,无法使用
printf("%d\n",a[4]);// 循环给数组a赋值
for(int data = 10,i = 0; i < 5; i++,data+=10)
{
a[i] = data;
}// 遍历输出
for(int i = 0; i < 5; i++)
{
printf("%d\n",a[i]);
}
return 0;
}
-
初始化:在定义的时候赋值,称为初始化
// 正常初始化
int a[5] = {100,200,300,400,500};int a[5] = {100,200,300,400,500,600}; // 错误,越界了
int a[ ] = {100,200,300}; // OK,自动根据初始化列表分配数组元素个数
int a[5] = {100,200,300}; // OK,只初始化数组元素的一部分
// 不能在使用变长数组的情况下初始化数组
int a[size] = {1,2,3};//编译出错
// 变长数组只能先定义再使用
int a[size]; // 正确的
a[0] = 10;
数组名[下标]
"下标":C语言的下标是从0开始,下标必须是>=0的整数
a[0]、a[1]、a[n]引用数组元素a[i]和普通变量一样,既可以作为左值,也可以作为右值
下标最小值为0,最大值为 元素个数 -1int a[5]; // 有效的下标范围是 0 ~ 4
a[0] = 1;
a[1] = 66;
a[2] = 21;
a[3] = 4;
a[4] = 934;a[5] = 62; // 错误,越界了
a = 10; // 错误,不可对数组名赋值
#include <stdio.h>
int main()
{
int size = 4;
//1)多个元素具有相同的数据类型,可以用一个集合来表示,数组
//int val1,val2,val3,val4;
//int arr[size];
//2)数组的初始化
//int arr[4] = {10,20,30,40};
//3)清空数组
int arr[4] = {0}; //数组中 arr[0] == 0,后面没有赋值的默认都是0
//数组元素的引用,通过数组的名字 + 下标 arr[0] 下标一定是大于等于0,下标最大值等于 元素的个数 -1
//arr[0] ---》val1
//arr[1] ---》val2
//arr[2] ---》val3
//arr[3] ---》val4
//arr[4] --内存访问越界,此时程序不会给你报错
for(int i=0; i<4; i++)
{
printf("arr[%d] addr:%p value:%d\n",i,&arr[i],arr[i]); //arr[0]
}
printf("&arr[0] :%p\n",&arr[0]);
printf("&arr[0]+1 :%p\n",&arr[0]+1);
return 0 ;
}
字符数组
-
概念:专门存放字符的数组,称为字符数组
-
初始化与元素引用:
char s1[5] = {'a', 'b', 'c', 'd', 'e'}; // s1存放的是字符序列,非字符串
char s2[6] = {'a', 'b', 'c', 'd', 'e', '\0'}; // s2存放了一个字符串char s[6] = {"abcde"}; // 使用字符串直接初始化字符数组
char s[6] = "abcde" ; // 大括号可以省略s[0] = 'A'; // 索引第一个元素,赋值为 'A'
#include <stdio.h>
int main(int argc, char const *argv[])
{
char Array[6] = {'D','A','V','I','D','\0'};
printf("%c\n",Array[3]); // 'k'
for(int i = 0; i < 6; i++)
{
printf("%c",Array[i]);
}
printf("\n");
// 输出字符串用%s
printf("%s\n",&Array[0]);
printf("%s\n",Array);char Array1[6] = {"DAVID"};// ""表示字符串,字符串末尾有\0
printf("%s\n",Array1);// 最常用的方法
char Array2[6] = "DAVID";
printf("%s\n",Array2);return 0;
}
数组偏移量
int Array[6] = {10,20,30,40,50,60};
// 数组地址偏移量
// 000000000061FE04,000000000061FE04
printf("%p,%p",&Array[1],&Array[0]+1);
数组元素地址解引用
对数组元素解引用可以获取地址空间里面的数据
int a =10;
printf("%d",a);
printf("%p\n",&a);//获取a的地址
------------------------------------------------------
char arr[5] = {' a ' , ' b ' ,' c ' ,' d ' ,' c ' };
printf("%c\n",arr[0]);//获取字符串a[0]的值 0;
printf("%c\n",*(arr +0));//同样也是获取a[0]的值 解释一下由于arr本身就是地址由于我们加0则获取的时a[0]的地址在进行解引用就能取到里面的值了
printf("%c\n",*(&arr[0]));//这是什么意思呢由于取地址符将会取到a[0]的地址然后在进行解引用就会取到里面的值
小窍门 *和&在一起将会抵消就跟没有的一样
printf("%c,%c\n",*(Array+1),*(&Array[1]));
printf("%c,%c\n",*(Array+2),*(&Array[2]));
printf("%c,%c\n",*(Array+3),*(&Array[3]));
字符串常量
-
字符串常量在内存中的存储,实质是一个匿名数组
-
匿名数组,同样满足数组两种涵义的规定
-
示例:
#include <stdio.h>
int main(int argc, char const *argv[])
{
printf("%s\n","abc");
printf("%c,%c\n","abc"[0],*("abc"+0));
printf("%c,%c\n","abc"[1],*("abc"+1));
printf("%c,%c\n","abc"[2],*("abc"+2));
printf("%d,%d\n","abc"[3],*("abc"+3)); // '\0'
return 0;
}
多维数组
int a1[3];
int a2[3];
int a[2][3];//a[0]-->a1 a[1]-->a2
第一种解释:
定义一个二维数组。该数组是由2个一维数组组成,分别是a[0] a[1]
每个一维数组由3个元素组成,所以二维数组有6个元素
数据类型 二维数组的名字[有多少个一维数组][每个一维数组有多少个元素]
// 代码释义:
// 1, a[2] 是数组的定义,表示该数组拥有两个元素
// 2, int [3]是元素的类型,表示该数组元素是一个具有三个元素的整 型数组
第二种解释:
该数组一共有2行,每行由3个元素组成(2行3列)
数据类型 二维数组名[行][列]
所谓的行:表示这个二维数组一共有多少个一维数组
所谓的列:表示这个二维数组每个一维数组有多少个元素
int a[2][3] = {{1,2,3}, {4,5,6}}; // 数组的元素是另一个数组
int a[2][3] = {{1,2,3}, {4,5,6}, {7,8,9}}; // 错误,越界了
int a[2][3] = {{1,2,3}, {4,5,6,7}}; // 错误,越界了int a[ ][3] = {{1,2,3}, {4,5,6}}; // OK,自动根据初始化列表分配数组元素个数
int a[2][3] = {{1,2,3}}; // OK,只初始化数组元素的一部分
// a[0] 代表第一个元素,这个元素是一个具有 3 个元素的数组:{1,2,3}
// a[1] 代表第二个元素,这个元素也是一个具有 3 个元素的数组:{4,5,6}printf("%d", a[0][0]); // 输出第一个数组的第一个元素,即1
printf("%d", a[1][2]); // 输出第二个数组的第三个元素,即6
//1、定义
//int arr[3][4];
//2、定义的时候初始化
//1)分行给二维数组初始化
/* int arr[3][4] = { {10,20,30,33},
{40,50,60,66},
{70,80,90,99}}; */
//2)将所有的数据全部写在一个大括号里面,按照数组的排列顺序进行赋值
//int arr[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
//int arr[3][4] = {{1,2,3,4},{5},6,7};//3)清空数组
//int arr[3][4] = {0};
//4)如果对全部元素进行赋值,则定义数组的时候可以省略第一维的长度
//int arr[][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
//int arr[][] = {1,2,3,4,5,6,7,8,9,10,11,12}; 错误
//int arr[3][] = {1,2,3,4,5,6,7,8,9,10,11,12}; 错误
二维数组解引用
// 二维数组初始化字符串
char buf1[2][5] = {"jack","rose"};
printf("%s,%s\n",&buf1[0][0],buf[0]);
printf("%s,%s\n",&buf1[1][0],buf[1]);// 取二维数组中的某个字符
printf("%c,%c,%c,%c\n",buf1[0][1],*(&buf1[0][1]),*(buf1[0]+1),*(*(buf1+0)+1));
printf("%c,%c,%c,%c\n",buf1[1][2],*(&buf1[1][2]),*(buf1[1]+2),*(*(buf1+1)+2));
练习1 : 定义二维数组,int buf[2] [3];将二维数组中每个元素的值和地址都打印出来
#include <stdio.h>
int main(int argc, char const *argv[])
{
char buf[2][4] = {"abc","efg"};printf("abc addrs : %p\n",buf[0]);
printf("a addrs : %p\n",&buf[0][0]);
printf("abc addr + 1 : %p\n",buf[0]+1);
printf("&abc addr + 1 : %p\n",&buf[0]+1);
printf("efg addrs : %p\n",buf[1]);
printf("efg addrs : %p\n",&buf[1][0]);printf("buf addrs : %p\n",buf);
printf("buf+1 addrs : %p\n",buf+1);printf("&buf addr : %p\n",&buf);
printf("&buf+1 addr : %p\n",&buf+1);
return 0;
}
用sizeof计算二维数组大小
char buf[2][4] = {"abc","efg"};
int n = sizeof(buf)/sizeof(buf[0][0]);//元素的个数
int line = sizeof(buf)/sizeof(buf[0]);//行数 = 二维的总大小除以一行的大小
int clu = sizeof(buf[0])/sizeof(buf[0][0]); // 列数 = 行的大小 除以 一个元素的大小