一维数组名
除了两种情况外一维数组的名字都是数组的第一个元素的指针
1 sizeof统计数组长度,返回的是数组长度的大小
2 对数组名取地址,得到的是一个数组指针,步长为整个数组大小
数组名是一个指针常量,指向是不可变的
数组索引下标可以为负数
数组指针的定义方式
typedef int(自定义类型)[大小]
是一个数组指针类型
typedef int(*自定义类型)[大小]
定义的是一个数组指针的指针
int (*p)[5]
1 //数组指针相当于把一个数组当做一个变量,类似于int float之类的来处理 2 #define _CRT_SECURE_NO_WARNINGS 3 #include<stdio.h> 4 //第一种通过typedef来定义一个别名来表示数组类型变量 5 void test01() 6 { 7 int a[5] = { 1,2,3,4,5 }; 8 typedef int(ARRARY_TYPE)[5];//这里就相当于把ARRARY_TYPE作为一个类型 9 //可以和int之类的正常来申明了处理 10 ARRARY_TYPE* b = &a;//后面的操作就可以类似的看作int等类型变量来处理 11 //这里相当于申请了一个ARRAY_TYPE类型的指针赋值为ARRARY_TYPE类型的a 12 for (int i = 0; i < 5; i++) 13 { 14 printf("%d\n", (*b)[i]);//这里的*b表示对b进行获取内容后得到的其实是a数组的首地址的内容 15 //然后可以把*b看成a再用正常数组来处理 16 } 17 } 18 19 //通过typedef来定义别名指针来表示数组指针 20 void test02() 21 { 22 int a[5] = { 1,2,3,4,5 }; 23 typedef int(*MY_TYPE)[5];//这里表示定义的是一个指针类型的类型 24 //类似于 typedef int* aaaa那么aaa就是一个定义的int *的指针类型来处理 25 MY_TYPE b = &a;//这里的b已经是一个指针了 26 for (int i = 0; i < 5; i++) 27 { 28 printf("%d\n", (*b)[i]);//这里和前面是一样的 29 } 30 } 31 //第三种方式直接用指针来处理 32 void test03() 33 { 34 int a[5] = { 1,2,3,4,5 }; 35 int(*p)[5] = &a;//这里就相当于一一对应来处理,用同样的指针数组类型 36 //来申明p指针对应a的地址来处理 37 for (int i = 0; i < 5; i++) 38 { 39 printf("%d\n", (*p)[i]); 40 } 41 } 42 43 void main(void) 44 { 45 //test01(); 46 //test02(); 47 test03(); 48 }//数组指针相当于把一个数组当做一个变量,类似于int float之类的来处理 49 #define _CRT_SECURE_NO_WARNINGS 50 #include<stdio.h> 51 //第一种通过typedef来定义一个别名来表示数组类型变量 52 void test01() 53 { 54 int a[5] = { 1,2,3,4,5 }; 55 typedef int(ARRARY_TYPE)[5];//这里就相当于把ARRARY_TYPE作为一个类型 56 //可以和int之类的正常来申明了处理 57 ARRARY_TYPE* b = &a;//后面的操作就可以类似的看作int等类型变量来处理 58 //这里相当于申请了一个ARRAY_TYPE类型的指针赋值为ARRARY_TYPE类型的a 59 for (int i = 0; i < 5; i++) 60 { 61 printf("%d\n", (*b)[i]);//这里的*b表示对b进行获取内容后得到的其实是a数组的首地址的内容 62 //然后可以把*b看成a再用正常数组来处理 63 } 64 } 65 66 //通过typedef来定义别名指针来表示数组指针 67 void test02() 68 { 69 int a[5] = { 1,2,3,4,5 }; 70 typedef int(*MY_TYPE)[5];//这里表示定义的是一个指针类型的类型 71 //类似于 typedef int* aaaa那么aaa就是一个定义的int *的指针类型来处理 72 MY_TYPE b = &a;//这里的b已经是一个指针了 73 for (int i = 0; i < 5; i++) 74 { 75 printf("%d\n", (*b)[i]);//这里和前面是一样的 76 } 77 } 78 //第三种方式直接用指针来处理 79 void test03() 80 { 81 int a[5] = { 1,2,3,4,5 }; 82 int(*p)[5] = &a;//这里就相当于一一对应来处理,用同样的指针数组类型 83 //来申明p指针对应a的地址来处理 84 for (int i = 0; i < 5; i++) 85 { 86 printf("%d\n", (*p)[i]); 87 } 88 } 89 90 void main(void) 91 { 92 //test01(); 93 //test02(); 94 test03(); 95 }
二维数组名
二维数组名除了两个特殊情况外是指向第一个一维数组的 数组指针
特殊情况:
sizeof()统计的是二维数组的大小
对数组名取地址返回的是一个二维数组指针,步长为整个数组大小
二维数组做函数参数
(int (*p)[])
(int p[][N])
(int array[N][N])
1 //二维数组名做函数参数 2 #define _CRT_SECURE_NO_WARNINGS 3 #include<stdio.h> 4 //第一种情况来表示二维数组做函数参数 5 void test01(int (*p)[3],int row,int col)// 6 { 7 for (int i = 0; i < row; i++) 8 { 9 for (size_t j = 0; j < col; j++) 10 { 11 printf("%d ", p[i][j]); 12 } 13 printf("\n"); 14 } 15 } 16 void test02(int p[3][3],int row,int col) 17 { 18 for (int i = 0; i < row; i++) 19 { 20 for (size_t j = 0; j < col; j++) 21 { 22 printf("%d ", p[i][j]); 23 } 24 printf("\n"); 25 } 26 } 27 void test03(int p[][3],int row,int col) 28 { 29 for (int i = 0; i < row; i++) 30 { 31 for (size_t j = 0; j < col; j++) 32 { 33 printf("%d ", p[i][j]); 34 } 35 printf("\n"); 36 } 37 } 38 39 void main() 40 { 41 int a[3][3] = { 42 {1,2,3}, 43 {4,5,6}, 44 {7,8,9} 45 }; 46 test01(a, 3, 3); 47 test02(a, 3, 3); 48 test03(a, 3, 3); 49 50 }
结构体基本概念
typedef
加上typedef可以给结构体起别名
typedef struct test{
}TEST;
不在开始加typdef可以直接给结构体初始化一个变量
struct test{
}test1;
匿名结构体
不给结构体命名,可以直接创建一个结构体变量
struct{
}test1;
在栈和堆上创建结构体
1 //在堆区和栈区创建结构体 2 #define _CRT_SECURE_NO_WARNINGS 3 #include<stdio.h> 4 #include<stdlib.h> 5 #include<string.h> 6 //在栈区创建结构体 7 void test01() 8 { 9 struct Link { 10 int a; 11 char b; 12 }; 13 struct Link a = { 1,'c' }; 14 } 15 //在堆区创建结构体 16 void test02() 17 { 18 struct Link { 19 int a; 20 char b; 21 }; 22 struct Link* p = (struct Link*)malloc(sizeof(struct Link)); 23 p->a = 1; 24 p->b = 'a'; 25 26 //用完了需要free掉 27 free(p); 28 } 29 30 void main() 31 { 32 test01(); 33 test02(); 34 }
结构体深浅拷贝
系统提供一个结构体的直接赋值操作:但是是逐字节操作,连指针地址也会改变
所以当在堆区时如果用直接赋值会导致释放的时候产生问题
1 //结构体嵌套指针数组 2 #define _CRT_SECURE_NO_WARNINGS 3 #include<stdio.h> 4 #include<stdlib.h> 5 struct Person 6 { 7 char* name; 8 int age; 9 }; 10 struct Person** Space() 11 { 12 struct Person** temp = (struct Person **)malloc(sizeof(struct Person*) * 3); 13 for (int i = 0; i < 3; i++) 14 { 15 //创建结构体内存 16 temp[i] = (struct Person *)malloc(sizeof(struct Person)); 17 //创建结构体的name字符串内存 18 temp[i]->name = (char *)malloc(sizeof(char) * 64); 19 //给name赋值 20 sprintf(temp[i]->name, "name=%d", i + 1); 21 temp[i]->age = i + 1; 22 } 23 return temp; 24 } 25 void Print_p(struct Person** p) 26 { 27 for (int i = 0; i < 3; i++) 28 { 29 printf("this name=%s", p[i]->name); 30 printf("this age=%d", p[i]->age); 31 } 32 } 33 void Delete(struct Person** p) 34 { 35 for (int i = 0; i < 3; i++) 36 { 37 free(p[i]->name); 38 p[i]->name = NULL; 39 free(p[i]); 40 p[i] = NULL; 41 } 42 } 43 44 void main() 45 { 46 struct Person** p = NULL; 47 p = Space(); 48 Print_p(p); 49 Delete(p); 50 free(p); 51 }