目录
数组
一维数组
某种数据类型变量的集合,在一块连续的内存上
1、作用:
方便定义相同数据类型的变量
int num[30];
等价于:
int num1;
int num2;
。。。
int num30;
2、数组框架:
元素的数据类型 变量名[元素个数];
元素的数据类型:基本数据类型:int char float。。。
除此之外:int *, char *, struct ....
元素个数:正整数
3、数组的定义方式:
(1)int a[3]; //未初始化定义,定义了一个有3个元素的数组,数组的元素类型为:int,数组的成员值为随机值
(2)int a[3]={1, 2, 3}; //全部初始化定义,定义了一个有3个元素的数组,数组的元素类型为:int,数组的成员值为
a[0] == 1, a[1] == 2, a[2] == 3
(3)int a[3]={1,2}; //部分初始化定义,定义了一个有3个元素的数组,数组的元素类型为:int,数组的成员值为
a[0] == 1, a[1] == 2, a[2] == 0
(4)int a[]={1, 2, 3, 4, 5}; //不定长数组,必须初始化,定义了一个有5个元素的数组,数组的元素类型为:int,数组的成员值为
a[0] == 1, a[1] == 2, a[2] == 3, a[3] == 4, a[4] == 5
(5)
int num;
scanf("%d", &num);
int a[num]; //变长数组,不能初始化,定义时,num的值必须确定,定义了一个有num个元素的数组,数组的元素类型为:int;
如果要给数组赋值,需要一个一个赋值
4、计算数组内存大小:
数组内存大小==数组元素类型所占字节数*元素个数
int a[5]={1, 2, 3, 4, 5};
sizeof(a) == sizeof(int)*5 == 4*5 ==20
5、访问数组元素:
int a[5]={1, 2, 3, 4, 5};
a[0] == 1 第一个元素的地址 &a[0] == &(a[0])
a[1] == 2 第二个元素的地址 &a[1] == &(a[1])
a[2] == 3第三个元素的地址 &a[2] == &(a[2])
a[3] == 4第四个元素的地址 &a[3] == &(a[3])
a[4] == 5第五个元素的地址 &a[4] == &(a[4])
访问数组的元素的下标:0~(数组元素个数-1)
6、数组名和数组的数据类型问题:
数组名是数组首元素地址
int a[5] = {1,2,3,4,5};
a == &a[0]
//去掉变量名,剩下的都是它的数据类型
int a[5];它的数据类型是:int ()[5]
char a[4];它的数据类型是:char ()[4]
数据类型+变量名
int a; 它的数据类型是:int
=========================================================================
学完数组要掌握的知识点:
1、定义数组
2、给数组赋值
3、把数组数据正确输出
4、数组的大小
5、数组的内存图
=========================================================================
二维数组
1、本质上也是一维数组
只是元素数据类型为一维数组的数组,就叫做二维数组
int a[2][3]; ==>int (a[2])[3];
2、二维数组定义模型
小数组的元素类型 变量名[N][M];
N -->大数组的元素个数,大数组指这个二维数组
M -->小数组的元素个数,小数组指的是二维数组的元素
小数组的元素类型 --》int, char, float........
3、二维数组定义和初始化
(1)int a[2][3]; //未初始化定义,定义了一个二维数组,该数组有两个元素,元素类型为:int ()[3],它的值为随机值
(2)int a[2][3]={{1, 2, 3}, {4, 5, 6}}; //全部初始化定义,定义了一个二维数组,该数组有两个元素,元素类型为:int ()[3],它的值:
a[0][0]==1, a[0][1] ==2, a[0][2]==3, a[1][0]==4, a[1][1]==5, a[1][2] == 6
(3)int a[2][3]={1, 2, 3, 4, 5, 6}; //全部初始化定义,定义了一个二维数组,该数组有两个元素,元素类型为:int ()[3],它的值:
a[0][0]==1, a[0][1] ==2, a[0][2]==3, a[1][0]==4, a[1][1]==5, a[1][2] == 6
(4)int a[2][3]={{1}, {4, 5}}; //部分初始化定义,定义了一个二维数组,该数组有两个元素,元素类型为:int ()[3],它的值:
a[0][0]==1, a[0][1] ==0, a[0][2]==0, a[1][0]==4, a[1][1]==5, a[1][2] == 0
(5)int a[2][3]={1, 2, 3}; //部分初始化定义,定义了一个二维数组,该数组有两个元素,元素类型为:int ()[3],它的值:
a[0][0]==1, a[0][1] ==2, a[0][2]==3, a[1][0]==0, a[1][1]==0, a[1][2] == 0
(6)int a[][3]={{1, 2, 3},{4}}; //不定长二维数组,定义了一个二维数组,该数组有两个元素,元素类型为:int()[3]二维数组,定义了一个二维数组,该数组有两个元素,元素类型为:int ()[3],它的值:
a[0][0]==1, a[0][1] ==2, a[0][2]==3, a[1][0]==4, a[1][1]==0, a[1][2] == 0
int a[2][]={{1, 2, 3},{4}};//小数组的元素个数必须确定的,否则编译会报错
4、二维数组的大小
二维数组的大小 == 小数组的元素类型大小*小数组的元素个数*大数组的元素个数== 大数组的元素个数*小数组的数据类型大小
int a[2][3];
sizeof(a) == sizeof(int)*2*3 == 4*2*3 == 24
5、数组元素的访问
int a[2][3]; //把这种数组称之为两行三列的数组
a[0][0]==1, --》元素地址为:&a[0][0]
a[0][1]==2, --》元素地址为:&a[0][1]
a[0][2]==3, --》元素地址为:&a[0][2]
a[1][0]==4, --》元素地址为:&a[1][0]
a[1][1]==5, --》元素地址为:&a[1][1]
a[1][2]==6, --》元素地址为:&a[1][2]
指针数组
1、概念:
本质是一个一维数组,它的元素类型是指针
2、定义模型
int a;
int b;
int c;
int d;
int *p1 = &a;
int *p2 = &b;
int *p3 = &c;
int *p4 = &d;
(int *) a[4]; ==> int *arry[4]; //定义一个有4个元素数组,元素类型为: int *
//arry[0] 的类型为: int *
//&arry[0]的类型为: int **
arry[0] = &a;
arry[1] = &b;
arry[2] = &c;
arry[3] = &d;
=========================================================================
指针
一级指针
1、概念:
指针也是一种变量,指针变量是用来存储对应变量的内存地址
2、如何定义一个指针变量
模型:被存储变量的数据类型 *变量名
int a;//定义了一个整型变量
a = 100; //把100转化为二进制存储到整型变量a里面
int *p; //定义了一个整型指针变量,准备用来存储整型变量的内存地址
p = &a; //获取变量a的地址把它存储到指针变量p里面
3、 怎么使用指针变量(解引用、取目标)
int a=100;
int *p=&a;
*p = 200; //通过指针变量访问,存储的内存地址的数据
//int *p=&a;
等价于
int *p;
p=&a;
不等价于:
int *p;
*p=&a;
4、指针内存大小:
32位系统占4个字节
64位系统占8个字节
5、指针加减-->内存地址加减
int a=100;
int *p=&a;
假设p的值为:0x1000
p == 0x1000
结论:
p+1 == 0x1001+sizeof(int) == 0x1004
char b=100;
char *b_p=&b;
结论:
b_p+1 == b_p+1*sizeof(char)
long long c=100;
long long *c_p=&c;
结论:
c_p+1 == c_p+1*sizeof(long long)
总结:
整型指针+1 == 整型指针+1*sizeof(int)
char指针+1 == char指针+1*sizeof(char )
char指针+2 == char指针+2*sizeof(char)
long long 指针+2 == long long 指针+2*sizeof(long long )
注意:
指针加减要考虑它存储对象的大小
内存地址加减也要考虑它存储对象的大小
内存地址包括两部分:地址值和存储的对象
6、指针变量数据类型问题
int a=200; a的数据类型是: int
200的类型为:int
&a的类型为:int *
int arry[3]; 该数组的数据类型为:int ()[3]
&arry 的类型为:int (*)[3]
int *p=&a; p的数据类型为:int *, 存储对象的类型为:int
&p 的类型:int **,存储对象的类型为:int *
&a的类型为:int *,存储对象的类型为:int
7、通用指针(万能指针)
void *p //通用指针(万能指针),可以合法存储任意一种类型的变量地址,但是存储之后类型会变成void *
void *型指针,没有存储对象
int a;
void *p = &a;
注意:通用指针要解引用必须先强制转换类型
8、NULL -->空指针
指针的零值:
#define NULL (void *)0x0
int *p; //p里面是随机值,也把这种指针称之为野指针,野指针是非常危险的,所以指针定义后如果未初始化,就赋值为NULL,比较安全
int *p = NULL;
*p = 100;
如果对NULL指针解引用会爆段错误:
gec@ubuntu:/mnt/hgfs/C语言/05/code$ ./a.out
Segmentation fault (core dumped) -->段错误(非法访问没有访问权限的内存)
=========================================================================
二级指针
1、概念:
指针变量用来存储变量内存地址
一级指针存储除了指针变量之外变量的地址
二级指针存储一级指针变量地址
2、定义模型
一级指针变量类型 *变量名;
char *p;
char **q = &p;
int *p1;
int **q1 =&p1;
3、二级指针的大小:
32位系统占4个字节
64位系统占8个字节
int **q;
4 == sizeof(q)
4、二级指针数据类型问题
int **q; q的数据类型为:-->int **
&q的类型为:-->int ***
int *p; p -->int *
&p -->int **
int a; a -->int
&a -->int *
=========================================================================
数组指针
1、概念:
本质是一级指针,用来存储数组的地址
int a[2]; //它的类型是:int ()[2]
//&a的类型为:int (*)[2]
定义一个相应类型的指针变量合法存储数组地址
int (*p)[2] = &a;
int a; //它的类型是:int
//&a的类型为:int *
int *p = &a;
2、定义模型:
char a[10]; //它的类型为:char ()[10]
//&a的类型为:char (*)[10]
char (*p)[10] = &a;
int a[2]; //它的类型是:int ()[2] 不等价的 int ()[10]
//&a的类型为:int (*)[2]
定义一个相应类型的指针变量合法存储数组地址
int (*p)[2] = &a;
int (*p1)[10] = &a; //不合法存储
int a[2][3]; //它的类型是:int ()[2][3]
//&a的类型为:int (*)[2][3]
int (*p)[2][3] = &a
模型:
数组的数据类型 *变量名
3、内存大小:
32位系统占4个字节
64位系统占8个字节