一、数组
1.1 数组认知:
静态分配空间(int a[100] 400个字节)----->空间利用率太差(1.不够用 2. 浪费空间)
所占内存空间特点:连续的(物理连续) -->malloc分配空间不一定是物理连续(malloc实现原理:链表链接所有空闲的空间,组成最终分配的空间)
1.2 如何使用数组
定义数组:该定义多大?char src[1024]; -->柔性数组!!!
注意事项:可变长数组c99
c89:定义数组时。必须定义其长度;
注意事项:不能在使用过程中通过修改变量,来扩充数组的内存空间
(选择方式):通常用宏来表达数组的代销,提高代码移植性
定义数组时,要清零
int a[3] = {0}
memset(a,0,sizeof(a));
[] = *();
数组++;不行
//柔性数组 struct node { int len; int array[0]; } struct node n; n.len = 10; n.array = (int *)malloc(sizeof(int) * n.len);
数组的使用
数组名的作用:
一维数组名:指针常量(元素类型的指针,无法改变),保存的数组首元素的地址
void func(char src[100])//用数组接的话,会退化成指针:char *src,所以要用指针接 { printf("%ld",sizeof(src));//输出是8 src++; } char buffer[1024] = "hello world"; func(buffer);
数组的地址
int a[3] printf("&a + 1 = %p",&a) //a:数组名,指针常量,保存数组首元素的地址 &a:对数组名取地址,等于数组的地址: *(&a) = a;对一位数组的地址取值等于数组首元素的地址 整型变量的地址用整型指针变量保存, 字符变量的地址用字符指针变量保存, 数组变量的地址用数组指针变量保存, 数组指针变量:变量,保存的是地址,地址数组的地址是数组的地址 int (*pa)[3] //整型数组指针变量:pa是一个变量,保存的地址,该地址是数组的地址,该数组是一个整型数组 pa = &a //*pa = a
二维数组
#include <stdio.h> int main() { int aa[2][2]; //int aa[2][] = {1,2,3,4} //二维数组只能省略列,不能省略行 // 二维数组名 //作用: for(int i = 0;i < 2; i++) { for(int j = 0;j < 2; j++) { scanf("%d",&aa[i][j]); scanf("%d",(*(aa + i) + j)) } } for(int i = 0;i < 2; i++) { for(int j = 0;j < 2; j++) { printf("aa[%d][%d] = %d\n",i ,j ,aa[i][j]); printf("aa[%d][%d] = %d\n",i ,j ,*(*(aa + i) + j)); } } }
二维数组:
aa指针常量,保存的是首个一维数组的地址;
&aa:二维数组的地址
*(&aa) = aa;对二维数组的地址取值等于首个一维数组的地址
*aa:首个一位数组的首个元素的地址
二维数组名:指针常量(一维数组指针,保存首个一维数组的地址)
三维数组
int aaa[2][2][2] = {{1,2,3,4},{5,6,7,8}}; //第一个下标:第几个个二维数组 //第二个下标:第几个个二维数组第几行 //第三个下标:第几个个二维数组第几列 //aaa[1][1][0]是7 //*aaa:首个二维数组的首个一位数组的地址 //**aaa:首个二维数组的首个一维数组的首元素的地址 //***aaa:首个二维数组的首个一维数组的首元素的值 //&aaa:三维数组的地址 //*(&aaa):对三维数组的地址取值等于首个二维数组的地址
1.3 数组名
#include <stdio.h> int main() { char str[100];//"hello" char ktr[2][100];//"hello1""hello2" char ptr[3][2][100];//"hello3""hello4""hello5""hello6" printf("input str:\n"); scanf("%s",str); printf("str = %s\n",str); printf("input ktr:\n"); for(int i = 0; i < 2; i++) { //scanf("%s",*(ktr + i)); scanf("%s",ktr[i]); } for(int i = 0; i < 2; i++) { printf("ktr[%d] = %s\n",i,*(ktr + i)); //scanf("%s",ktr[i]); } printf("input ptr:\n"); for(int i = 0; i < 2; i++) { for(int j = 0; j < 2; j++) { scanf("%s",*(*(ptr + i) + j));//ptr[i][j] } } for(int i = 0; i < 2; i++) { for(int j = 0; j < 2; j++) { printf("ptr = %s\n",*(*(ptr + i) + j));//ptr[i][j] } } return 0; }
1.4 数组指针
数组指针变量
//数组指针 int (*paa)[2][2] = &aa;//数组指针变量:指向一个二维数组(保存二维数组地址) int (*paaa)[2][2][3] = &aaa
如何定义数字组指针变量?右左法则 int (*p)
一维数组名,用指针接
void print2( char *str)
二维数组名,用一维数组指针接
void print2( char (*ktr)[100])
三维数组名,用二维数组数组指针接
void print2( char (*ptr)[2][100])
1.5 指针数组
指针数组:数组里保存的都是指针
#include <stdio.h> int main() { int *pi[3];//指针数组,存放 //int (*pa)[3];//数组指针,是指针,指向数组,sizeof(pa) = 8 char *pc[3] = }
一维数组名,用元素指针接,而元素就是指针,则就是元素指针的指针来接,即二级指针
void print4(char **pc)
1.6 指针与数组的区别
空间分配:指针:动态,数组:静态(优缺点)
访问效率:数组 > 指针 指针更灵活
安全性:数组高
函数形参:数组全都退化成指针
1.7 指针与数组的复杂说明
右左法则:右左法则