10.指针进阶
- 互联网
- 2025-09-22 07:57:01

这里写目录标题 1. 字符指针2. 指针数组3. 数组指针3.1 int (\*p)\[10\];3.2 arr; &arr\[ \]; &arr.3.3 数组指针的使用 4. 数组传参和指针传参4.1 一维数组传参4.2 二维数组传参4.3 一级指针传参4.4 二级指针传参 5. 函数指针 1. 字符指针 int main() { char ch = 'w'; char *pc = &ch;//pc就是字符指针 *pc = 'a'; return 0; } int main() { char arr[] = "abcdef"; //[a b c d e f \0] const char* p = "abcdef";//常量字符串 //把首字符a的地址赋值给p //p指向a的地址 printf("%s\n", p); printf("%c\n", *p); return 0; } abcdef a
分析代码
int main() { char str1[] = "hello RuaRua."; char str2[] = "hello RuaRua."; const char* str3 = "hello RuaRua."; const char* str4 = "hello RuaRua."; if (str1 == str2) printf("str1 and str2 are same\n"); else printf("str1 and str2 are not same\n"); if (str3 == str4) printf("str3 and str4 are same\n"); else printf("str3 and str4 are not same\n"); return 0; } str1 and str2 are not same str3 and str4 are same C/C++会把常量字符串存储到单独的一个内存区域,str3 和 str4 是指向常量字符串的指针,它们指向的是存储在静态存储区只读部分的字符串常量 "hello RuaRua.",这个字符串常量与 str1和str2 中存储的字符串虽然内容相同,但在内存中是不同的存储位置。 2. 指针数组 int* arr1[10]; //存放 整形指针 的数组 char *arr2[10]; //存放 一级字符指针 的数组 char **arr3[10];//存放 二级字符指针 的数组eg.模拟二维数组
int main() { int arr1[] = { 1,2,3,4,5 }; int arr2[] = { 2,3,4,5,6 }; int arr3[] = { 3,4,5,6,7 }; int* arr[3] = { arr1,arr2,arr3 }; int i = 0; for (i = 0; i < 3; i++) { int j = 0; for (j = 0; j < 5; j++) { printf("%d ", arr[i][j]); } printf("\n"); } return 0; } 1 2 3 4 5 2 3 4 5 6 3 4 5 6 7 3. 数组指针 3.1 int (*p)[10]; int (*p)[10]; //p是数组指针变量,指向的是数组 3.2 arr; &arr[ ]; &arr. int main() { int arr[10] = { 0 }; printf("%p\n", arr); printf("%p\n", &arr[0]); printf("%p\n", &arr); printf("%d\n", sizeof(arr)); return 0; } 008ff858 arr 是数组首元素地址 008ff858 &arr[0] 是数组首元素地址 008ff858 &arr 是整个数组地址 40 sizeof(arr) 计算整个数组大小,arr表示整个数组 名称值类型arr0x008ff858 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}int[10]&arr[0]0x008ff858 {0}int *&arr0x008ff858 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}int(*)[10] int main() { int arr[10] = { 0 }; printf("%p\n", arr); printf("%p\n", arr+1); printf("%p\n", &arr[0]); printf("%p\n", &arr[0]+1); printf("%p\n", &arr); printf("%p\n", &arr+1); return 0; } 00F3F840 00F3F844 00F3F840 00F3F844 00F3F840 00F3F868-->0x28-->40 int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,0 }; //把数组arr的地址赋值给数组指针变量p //int[10] * p = &arr;//err int(*p)[10] = &arr;//p是数组指针,存放数组地址 return 0; } arr 的类型是 int [10] p 的类型是 int(*)[10] &arr 的类型是 int(*)[10] 3.3 数组指针的使用一般在二维数组中使用,常规写法:
void Print(int arr[3][5], int r, int c)//row,column { int i = 0; for (i = 0; i < 3; i++) { int j = 0; for (j = 0; j < 5; j++) { printf("%d ", arr[i][j]); } printf("\n"); } } int main() { int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 }; Print(arr, 3, 5); return 0; }二维数组,每一行可以理解为数组的一个元素 每一行是一个一维数组 二维数组是 一维数组的数组
arr -->首元素地址 -->第一行地址 -->一维数组地址 void Print(int(*p)[5], int r, int c) { int i = 0; for (i = 0; i < 3; i++) { int j = 0; for (j = 0; j < 5; j++) { printf("%d ", *(*(p + i) + j)); } printf("\n"); } } (p + i):指针移动到i数组 *(p + i):i数组的地址 (*(p + i) + j):i数组j元素的地址 *(*(p + i) + j):得到元素 4. 数组传参和指针传参 4.1 一维数组传参 void test1(int arr[5], sz) {} void test2(int* p, sz) {} int main() { int arr[5] = { 0 }; test1(arr, 5); test2(arr, 5); return 0; } 4.2 二维数组传参 void test1(int arr[3][5], int r, int c) {} void test2(int(*p)[5], int r, int c) {} int main() { int arr[3][5] = {0}; test1(arr, 3, 5); test2(arr, 3, 5); return 0; }int arr[3][5]:是二维数组类型的形参,虽然写成 int arr[3][5] ,但实际上会退化为指向包含 5 个 int 类型元素的数组的指针,即 int (*)[5] 类型。 int (*p)[5]:是指针类型的形参,p 是一个指向包含 5 个 int 类型元素的数组的指针。和 int arr[3][5] 本质上是等价的,都用于接收二维数组的首地址,即第一行的地址。
4.3 一级指针传参 void print(int* p, int sz) { int i = 0; for (i = 0; i < sz; i++) { printf("%d\n", *(p + i)); } } int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9 }; int* p = arr; int sz = sizeof(arr) / sizeof(arr[0]); //一级指针p,传给函数 print(p, sz); return 0; }当函数的参数为一级指针,函数能接收什么参数?
void test(int* p)//函数能接收什么参数? { } int n = 0; int *ptr = &n; int arr[] = "abcdef"; test (ptr); test (&n); test (arr); 4.4 二级指针传参 void test(int** ptr) { printf("num = %d\n", **ptr); } int main() { int n = 10; int* p = &n; int** pp = &p; test(pp); test(&p); return 0; }当函数的参数为二级指针的时候,可以接收什么参数?
void test(int** p) { } int main() { int n = 10; int* p = &n; int** pp = &p; int* arr[10]; test(&p); test(pp); test(arr); return 0; } 5. 函数指针 void test() { printf("hehe\n"); } int main() { printf("%p\n", test); printf("%p\n", &test); return 0; } 006013B6 006013B6 test和&test都是函数地址eg
void test(char* pc, int arr[10]) { } int main() { void (*pf)(char*, int arr[]) = test; return 0; }eg
int Add(int x, int y) { return x + y; } int main() { int arr[10] = { 0 }; int(*pa)[10] = &arr;//类比 int(*pf)(int, int) = &Add; //pf是函数指针变量 return 0; }使用指针调用函数
int Add(int x, int y) { return x + y; } int main() { int(*pf)(int, int) = &Add; int r = Add(3, 5); printf("%d\n", r); int m = (*pf)(4, 5); //--> int m = pf(4, 5); //pf和Add一回事 printf("%d\n", m); return 0; }eg1.代码分析
(*(void (*)())0)(); void (*p)()-->p是函数指针 void (*)() -->函数指针类型 (void (*)())0-->强制类型转换, 0转换成 void (*)(), 0的地址中存放着这个函数 *(void (*)())0-->解引用,调用这个函数 (*(void (*)())0)()-->调用时无参数 (*(void (*)())0)();-->调用0地址处的函数eg2.代码分析
void (*signal(int , void(*)(int)))(int); void (*p)(int); -->函数指针 void(*)(int)-->函数指针指向一个int类型的参数,返回类型void signal(int , void(*)(int))--> signal 函数(类型 int ,函数指针类型 void(*)(int))简化
//typedef重定义 typedef unsigned int uint; typedef int* ptr_t; typedef int(*parr_t)[10]; typedef int(*pf_t)(int,int); int main() { uint u1; ptr_t p1; int* p2; return 0; } void (*signal(int , void(*)(int)))(int); ---> typedef void(*pf_yt)(int); //void (*signal(int, void(*)(int)))(int); pf_yt signal(int, pf_yt);上一篇
linux服务器更新jar包脚本