二级指针
指针可以指向一份普通类型的数据,例如 int、double、char 等,也可以指向一份指针类型的数据,例如 int *、double *、char * 等。
如果一个指针指向的是另外一个指针,我们就称它为二级指针,或者指向指针的指针。
#define _CRT_SECURE_NO_WARNINGS#include#include#include#includeint main0501(){ int a1[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9,10,11,12} }; int a2[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };//常用此类方式 int a3[][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 }; for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { printf("%d ", a3[i][j]); } printf("\n"); } printf("\n"); //二维数组的数组名代表第0行的首地址(区别于第0行首元素地址,值相同) //步长不同 printf("a:%d,a+1%d\n", a3, a3 + 1);//a代表一维数组首行首地址 相差16 printf("%d, %d\n", *(a3 + 0),*(a3+1)+1);//第0行首元素地址 差16 printf("%d, %d\n", a3[0], a3[0]+1); int a[][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 }; //a:代表首行首地址 //a+i -> &a[i]:代表第i行首地址 //*(a+i) -> a[i]:代表第i行首元素地址 //*(a+i)+j -> &a[i][j]:第i行第j列元素的地址 //*(*(a+i)+j) -> a[i][j]:代表第i行第j列元素的值 return 0;}void printA(int* a, int n){ for (int i = 0; i < n; i++) { printf("%d ", a[i]); } printf("\n");}int main0502(){ int a[][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 }; printA((int*)a,sizeof(a)/sizeof(a[0][0])); return 0;}int main0503(){ int a[][10] = { 1,2,3,4,5,6,7,8,9,10,11,12 }; //3个 a[4]的一维数组 //定义数组指针变量 //指向一维数组的指针 int(*p)[10]; //p = &a;//整个二维数组首地址 p=a; p = a;//第0行首地址 printf("p:%d ,p+1:%d\n", p, p + 1);//相差10*4=40 int n = sizeof(a) / sizeof(a[0]);//行 int nj = sizeof(a[0]) / sizeof(a[0][0]);//列 for (int i = 0; i < n; i++) { for (int j = 0; j < nj; j++) { //printf("%d ", p[i][j]); printf("%d ", *(*(p + i) + j)); } printf("\n"); } int t[10]; //测一维数组长度:sizeof()首行首元素地址 printf("sizeof(t)=%d ,sizeof(&t)=%d\n", sizeof(t), sizeof(&t)); //int a[2][10] printf("sizeof(a[0])=%d ,sizeof(&a[0])=%d\n", sizeof(a[0]), sizeof(&a[0])); printf("sizeof(*(a+0))=%d ,sizeof(a+0)=%d\n", sizeof(*(a + 0)), sizeof(a + 0));//两行等价 return 0;}void printArray(int a[3][4]){ for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { printf("%d ", a[i][j]); } printf("\n"); } printf("\n");}void printArray2(int a[][4])//步长为4*4=16{ for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { printf("%d ", a[i][j]); } printf("\n"); } printf("\n");}void printArray3(int** a)//err 指针的步长不同 这个步长为4{ for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { printf("%d ", a[i][j]); } printf("\n"); } printf("\n");}//数组指针类型typedef int(*P)[4];void printArray4(P a)//数组指针{ for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { printf("%d ", a[i][j]); } printf("\n"); } printf("\n");}int main(){ int a[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 }; printArray4(a); return 0;}练习1:
#define _CRT_SECURE_NO_WARNINGS#include#include#include#include#define NUM(a) (sizeof(a)/sizeof(*a))/*功能:找到数组中中指定字符串的位置参数:table:字符串数组(指针数组)首地址size:数组元素个数key:匹配字符串,如"do"pos:匹配字符串在数组中的位置,如果"do"在keyword[]中的位置为4返回值: 成功:0 失败:非0*/int searchKeyTable(const char* table[], const int size, const char* key, int* pos){ int n = -1; if (table==NULL||key==NULL||pos==NULL) { return -1; } for (int i = 0; i < size; i++) { if (strcmp(table[i], key) == 0) { n = i; break; } } if (n==-1) { return -2; } *pos = n + 1; return 0;}int main(){ char* keywords[] = { "while","case","static","do" }; int pos = 0; int ret = 0; ret = searchKeyTable(keywords, NUM(keywords), "do", &pos); if (ret!=0) { printf("seachKeyTable err:%d\n", ret); system("pause"); return ret; } printf("%s在keyword中的位置是:%d\n", "do", pos); return 0;}练习2:
#define _CRT_SECURE_NO_WARNINGS#include#include#include#includeint sort(char** array1, int num1, char(*array2)[30], int num2, char** myp3, int* num3){ if (array1==NULL||array2==NULL||myp3==NULL||num3==NULL) { return -1; } //创建一个指针数组 char* temp[num1+num2] char** temp = (char**)malloc(sizeof(char*) * (num1 + num2)); if (temp==NULL) { return -2; } //给每个指针分配内存(指向堆区) for (int i = 0; i < num1; i++) { temp[i] = (char*)malloc(sizeof(char)*(strlen(array1[i])+1)); strcpy(temp[i], array1[i]); } for (int i=num1,j=0; i < num1+num2; i++,j++) { //array2[j]不是i temp[i] = (char*)malloc(sizeof(char) * (strlen(array1[j]) + 1)); strcpy(temp[i], array2[j]); } char* p = NULL; //排序 for (int i = 0; i < num1+num2-1; i++) { for (int j = i+1; j < num1+num2; j++) { if (strcmp(temp[i],temp[j])>0)//升序 { p = temp[i]; temp[i] = temp[j]; temp[j] = p; } } } //间接赋值 *myp3 = temp; *num3 = num1 + num2; return 0;}void free_buf(char*** p3,int n){ if (p3==NULL) { return; } char** temp = *p3; for (int i = 0; i < n; i++) { if (temp[i]!=NULL) { free(temp[i]); temp[i] = NULL; } } if (temp!=NULL) { free(temp); *p3 = NULL; }}int main(){ int ret = 0; char* p1[] = { "aa","cccc","bbbbb" }; char buf2[][30] = { "","","" }; char** p3 = NULL; int len1, len2, len3, i = 0; len1 = sizeof(p1) / sizeof(*p1); len2 = sizeof(buf2) / sizeof(buf2[0]); for (int i = 0; i < len1; i++) { printf("%s ,", p1[i]); } for (int i = 0; i < len2; i++) { printf("%s ,", buf2[i]); } printf("\n\n"); /* 功能: 1.把指针数组p1的字符串取出来 2.把二维数组buf2的字符取出来 3.上面的字符串放在p3,p3是在堆区分配的二维内存 4.对p3中字符串进行排序,通过strcmp进行排序 参数: p1:指针数组首地址,char*p1[]={ "aa","cccc","bbbbb" }; len1:p1元素个数 buf2:二维数组首元素地址,char buf2[][30]={"","",""}; len2:buf2字符串的行数 p3:二级指针的地址,需要在函数内分配二维内存,保存p1和buf2的字符串,还需要排序 len3:保存p3中的字符串个数 返回值: */ ret = sort(p1, len1, buf2, len2, &p3, &len3); if (ret!=0) { printf("sort err:%d\n", ret); system("pause"); return ret; } for (int i = 0; i < len3; i++) { printf("%s ,", p3[i]); } //释放p3所指向的内存 //在函数内部把p3的值赋值为NULL free_buf(&p3,len3); return 0;}结构体的初始化
#define _CRT_SECURE_NO_WARNINGS#include#include#include#include/*1.结构体类型定义2.结构体变量定义3.结构体变量初始化4.typedef 修改类型名5.点运算符 '.' '->'操作结构体成员6.结构体也是一种数据类型*///1.结构体类型定义//struct 关键字//struct Teacher 合在一起才是类型struct Teacher{ char name[50]; int age;};//2.结构体变量定义// 1.先定义类型,再定义变量(常用)struct Teacher t1;//全局变量//2.定义类型同时定义变量struct Teacher2{ char name[50]; int age;}t3={"tom",15};struct{ char name[50]; int age;}t5;//3.结构体变量的初始化//定义变量时直接初始化,通过{}struct Teacher t7 = { "lili",12 };//4.typedef 改类型名typedef struct Teacher3{ char name[50]; int age;}Teacher3;struct Teacher3 t8;Teacher3 t9;int main(){ //1.先定义类型,再定义变量(常用) struct Teacher t2;//局部变量 printf("%s ,%d\n", t7.name, t7.age); //5.点运算符 '.' '->'操作结构体成员 /* struct Teacher { char name[50]; int age; }; */ strcpy(t2.name, "xiaoming"); t2.age = 22; printf("%s ,%d\n", t2.name, t2.age); //结构体在初始化之前必须分配空间,不能指向空 struct Teacher* p = NULL; p = &t2; strcpy(p->name, "xiaoming"); p->age = 22; printf("%s ,%d\n", p->name,p->age); return 0;}结构体之间的赋值
#define _CRT_SECURE_NO_WARNINGS#include#include#include#include//在定义结构体类型时,不能给成员赋值//结构体只是一个类型,还没有分配空间//只有根据其类型定义变量时,才分配空间,有空间后才能赋值typedef struct Teacher{ char name[50]; int age;}Teacher;copyTeacher(Teacher to,Teacher from)//值传递不能修改实参的值{ to = from; printf("[copyTeacher]%s ,%d\n", to.name, to.age);//地址传递可以先修改实参的值}copyTeacher2(Teacher* to, Teacher* from){ *to = *from; printf("[copyTeacher]%s ,%d\n", to->name, to->age);}void fun(int to, int from){ to = from;}int main(){ Teacher t1 = { "tom",21 }; //相同类型的两个结构体变量,可以相互赋值 //把t1成员变量内存的值拷贝给t2成员变量的内存 Teacher t2 = t1; printf("%s %d\n", t2.name, t2.age); Teacher t3; memset(&t3, 0, sizeof(t3)); copyTeacher2(&t3,&t1);//将t1拷贝给t3 printf("[t3]%s ,%d\n", t3.name, t3.age); int a = 10; int b = 0; fun(a, b);//将b的值给a printf("a=%d\n", a);//值传递 形参不能修改实参的值 需要地址传递 return 0;}