- 字符指针
- C/C++会把常量字符串存储到单独的一个内存区域,当几个指针指向同一个字符串的时候,他们实际会指向同一块内存。
- 用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。
- 代码 const char* pstr = "hellobit";//本质是把字符串 hellobit 首字符的地址放到了pstr中。
- code示例
#include
int main() { char ch = 'w'; char* pc = &ch; *pc = 'd'; printf("%c %pn", *pc, pc); // d 000000DB503BFA84 const char* pstr = "hellobit";//本质是把字符串 hello bit. 首字符的地址放到了pstr中。 printf("%s %c %d %pn", pstr, *pstr, strlen(pstr), &pstr); // hellobit h 8 000000E4813BFAE8 char str1[] = "hello bit."; char str2[] = "hello bit."; const char* str3 = "hello bit."; const char* str4 = "hello bit."; // 用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。 // 所以str1和str2不同,str3和str4不同。 if (str1 == str2) printf("str1 == str2n"); else printf("str1 != str2n"); // str1 != str2 // str3和str4指向的是一个同一个常量字符串 // C/C++会把常量字符串存储到单独的一个内存区域, // 当几个指针指向同一个字符串的时候,他们实际会指向同一块内存。 if (str3 == str4) printf("str3 == str4n"); // str3 == str4 else printf("str3 != str4n"); return 0; }
- 指针数组
- code示例
#include
int main() { int* arr1[10]; //整形指针的数组 char* arr2[4]; //一级字符指针的数组 char** arr3[5];//二级字符指针的数组 return 0; }
- code示例
- 数组指针
- 数组指针的定义
- 数组指针 是 指针 ,不是数组
-
数组指针:指向数组的指针
- 整形指针 : int * pint ; 指向 整形数据 的 指针 。
- 浮点型指针: float * pf; 指向 浮点型数据的指针。
-
code示例
#include
int main() { int* p1[10]; //整形的指针数组 int(*p2)[5]; // 解释:p2先和*结合,说明p2是一个指针变量,然后指着指向的是一个大小为5个整型的数组。 // 所以p是一个,指向一个数组,叫数组指针。 // 同时:[]的优先级要高于*号的,所以必须加上()来保证p先和*结合。 return 0; }
- &数组名 VS 数组名
- 其实&arr和arr,值是一样的,但是意义应该不一样的。
实际上: &arr 表示的是数组的地址,而不是数组首元素的地址。(细细体会一下); arr 是数组名,数组名arr表示数组首元素的地址。- 下例中 &arr 的类型是: int(*)[10] ,是一种数组指针类型。数组的地址+1,跳过整个数组的大小,所以 &arr+1 相对于 &arr的差值是40。
- code示例
#include
int main() { int arr[10] = { 0 }; // &arr和arr,值是一样的,但是意义应该不一样的。 // &arr 表示的是数组的地址,而不是数组首元素的地址 // arr 是数组名,数组名表示数组首元素的地址 printf("%pn", arr); // 000000B27340F5D8 printf("%pn", &arr); // 000000B27340F5D8 printf("arr+1 = %pn", arr + 1); // arr+1 = 000000B27340F5DC printf("&arr+1= %pn", &arr + 1); // &arr+1= 000000B27340F600 return 0; }
- 其实&arr和arr,值是一样的,但是意义应该不一样的。
- 数组指针的使用
- 数组指针指向的是数组,数组指针中存放的应该是数组的地址。
- code示例
#include
void print_arr1(int arr[3][5], int row, int col) { int i = 0; for (i = 0; i < row; i++) { for (int j = 0; j < col; j++) { printf("arr1[%d][%d] = %d ",i, j, arr[i][j]); } printf("n"); } } void print_arr2(int(*arr)[5], int row, int col) { int i = 0; for (i = 0; i < row; i++) { for (int j = 0; j < col; j++) { printf("arr2[%d][%d] = %d ", i, j, arr[i][j]); } printf("n"); } } int main() { int arr[3][5] = { 1,2,3,4,5,6,7,8,9,10 }; print_arr1(arr, 3, 5); //数组名arr,表示首元素的地址 //但是二维数组的首元素是二维数组的第一行 //所以这里传递的arr,其实相当于第一行的地址,是一维数组的地址 //可以数组指针来接收 print_arr2(arr, 3, 5); return 0; }
- 数组指针的定义
- 数组参数、指针参数
- 一维数组传参
- code示例
#include
void test_a(int arr[])//ok {} void test_b(int arr[10])//ok {} void test_c(int* arr)//ok {} void test2_a(int* arr[20])//ok {} void test2_b(int** arr)//ok {} int main() { int arr[10] = { 0 }; int* arr2[20] = { 0 }; test_a(arr); test_b(arr); test_c(arr); test2_a(arr2); test2_b(arr2); }
- code示例
- 二维数组传参
- 二维数组传参,函数形参的设计只能省略第一个[]的数字。
//因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。
//这样才方便运算。 - code示例
#include
void test_a(int arr[3][5])//ok {} //void test_b(int arr[][])//语法有误 //{} void test_c(int arr[][5])//ok {} //总结:二维数组传参,函数形参的设计只能省略第一个[]的数字。 //因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。 //这样才方便运算。 void test_d(int* arr)//ok {} void test_e(int* arr[5])//ok {} void test_f(int(*arr)[5])//ok {} void test_g(int** arr)//ok {} int main() { int arr[3][5] = { 0 }; test_a(arr); // test_b(arr); test_c(arr); test_d(arr); test_e(arr); test_f(arr); test_g(arr); }
- 二维数组传参,函数形参的设计只能省略第一个[]的数字。
- 一维指针传参
- 当一个函数的参数部分为一级指针的时候,函数能接收什么参数?数组
- code示例
#include
void print(int* p, int sz) { int i = 0; for (i = 0; i < sz; i++) { printf("p[%d] = %dn",i, *(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; }
- 二维指针传参
- 二级指针:接受二级地址作为参数
- code示例
#include
void test(int** ptr) { printf("num = %dn", **ptr); } int main() { int n = 10; int* p = &n; int** pp = &p; test(pp); // num = 10 test(&p); // num = 10 char* arr[10]; test(arr);// 出错 return 0; }
- 一维数组传参
- 函数指针
- 调用函数输出两个地址,这两个地址是 test 函数的地址。
- 如何保存数组的地址? 首先,能给存储地址,就要求pfun1或者pfun2是指针,那哪个是指针?
答案是:
pfun1可以存放。pfun1先和*结合,说明pfun1是指针,指针指向的是一个函数,指向的函数无参数,返回值类型为void。 - code示例
#include
void test() { printf("hehen"); } //下面pfun1和pfun2哪个有能力存放test函数的地址? void (*pfun1)(); void* pfun2(); int main() { printf("%pn", test); // 00007FF7B97A146A printf("%pn", &test); // 00007FF7B97A146A return 0; }
- 如何保存数组的地址? 首先,能给存储地址,就要求pfun1或者pfun2是指针,那哪个是指针?
- 调用函数输出两个地址,这两个地址是 test 函数的地址。
- 函数指针数组
- 数组 是一个存放 相同类型数据 的存储空间
- 把 函数的地址 存到一个 数组 中,那这个数组就叫 函数指针数组
-
函数指针数组
如何
定义
:int (*parr1[10])();
-
解析:
parr1
先和
[]
结合,说明
parr1是数组
,数组的
内容
是
int (*)()
类型的
函数指针
。
函数指针数组的用途: 转移表
-
解析:
parr1
先和
[]
结合,说明
parr1是数组
,数组的
内容
是
int (*)()
类型的
函数指针
。
-
code示例
#include
int add(int a, int b) { return a + b; } int sub(int a, int b) { return a - b; } int mul(int a, int b) { return a * b; } int div(int a, int b) { return a / b; } int main() { int x, y; int input = 1; int ret = 0; int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //转移表 while (input) { printf("*************************n"); printf(" 1:add 2:sub n"); printf(" 3:mul 4:div n"); printf("*************************n"); printf("请选择:"); scanf("%d", &input); if ((input <= 4 && input >= 1)) { printf("输入操作数:"); scanf("%d %d", &x, &y); ret = (*p[input])(x, y); // 函数指针数组 } else printf("输入有误n"); printf("ret = %dn", ret); } return 0; }
- 指向函数指针数组的指针
- 指向函数指针数组的指针是一个 指针;
- 指针指向一个 数组 ,数组的元素都是函数指针。
- code示例
#include
void test(const char* str) { printf("%sn", str); } int main() { //函数指针pfun void (*pfun)(const char*) = test; //函数指针的数组pfunArr void (*pfunArr[5])(const char* str); pfunArr[0] = test; //指向函数指针数组pfunArr的指针ppfunArr void (*(*ppfunArr)[5])(const char*) = &pfunArr; return 0; }
- 回调函数
- 回调函数就是一个通过函数指针调用的函数。
- 如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
- code示例
// 代码示例1 //#include
// qosrt函数的使用者得实现一个比较函数 //int int_cmp(const void* p1, const void* p2) { // return (*(int*)p1 - *(int*)p2); //} // //int main() //{ // int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 }; // int i = 0; // // qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp); // 从小到大排列 // // for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) // { // printf("%d ", arr[i]); // } // printf("n"); // return 0; //} // 代码示例2 // bubble() 模拟 实现qsort() #include int int_cmp(const void* p1, const void* p2) { return (*(int*)p1 - *(int*)p2); } void _swap(void* p1, void* p2, int size) { int i = 0; for (i = 0; i < size; i++) { char tmp = *((char*)p1 + i); *((char*)p1 + i) = *((char*)p2 + i); *((char*)p2 + i) = tmp; } } void bubble(void* base, int count, int size, int(*cmp)(void*, void*)) { int i = 0; int j = 0; for (i = 0; i < count - 1; i++) { for (j = 0; j < count - i - 1; j++) { if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0) { _swap((char*)base + j * size, (char*)base + (j + 1) * size, size); } } } } int main() { int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 }; //char *arr[] = {"aaaa","dddd","cccc","bbbb"}; int i = 0; bubble(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp); // 冒泡排序 for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) { printf("%d ", arr[i]); } printf("n"); return 0; }
- 回调函数就是一个通过函数指针调用的函数。
- 指针和数组题目解析
- code示例
#define _CRT_SECURE_NO_WARNINGS 1 #include
int main() { // &arr 表示的是数组的地址,而不是数组首元素的地址。 // arr 是数组名,数组名arr表示数组首元素的地址。 //一维数组 printf("一维数组 int a[] = { 1,2,3,4 }; n"); int a[] = { 1,2,3,4 }; printf("数组的地址 = %pn", &a); // 0092FDD4 &arr 表示的是数组的地址 printf("数组的大小 = %dn", sizeof(&a)); // 4 printf("数组地址的strlen = %dn", strlen(&a)); // 1 printf("数组的地址 = %pn", *&a); // 0092FDD4 printf("数组所占字节数 = %dn", sizeof(*&a)); // 16 printf("数组地址的strlen = %dn", strlen(*&a)); // 1 printf("第一个元素地址 = %pn", a); // 0092FDD4 数组a首元素的地址 printf("数组所占字节数 = %dn", sizeof(a)); // 16 4个元素 * 4个字节 = 16 printf("第一个元素地址的strlen = %dn", strlen(a)); // 1 printf("第一个元素地址 = %pn", (a + 0)); // 0092FDD4 数组首元素的地址 printf("第一个元素地址的大小 = %dn", sizeof(a + 0)); // 4 printf("第一个元素地址的strlen = %dn", strlen(a + 0)); // 1 printf("下标访问:第一个元素地址 = %pn", &a[0]); // 0092FDD4 printf("下标访问:第一个元素地址的大小 = %dn", sizeof(&a[0])); // 4 printf("下标访问:第一个元素地址的strlen = %dn", strlen(&a[0])); // 1 printf("第一个元素值 = %dn", *a); // 1 解引用:解析出数组首元素地址中,存放的值 printf("第一个元素值的大小 = %dn", sizeof(*a)); // 4 // printf("第一个元素值的strlen = %dn", strlen(*a)); // 异常 printf("数组所有4个元素之后的地址 = %pn", (&a + 1)); // 0092FDE4 printf("此地址的大小 = %dn", sizeof(&a + 1)); // 4 printf("此地址的strlen = %dn", strlen(&a + 1)); // 11 printf("第二个元素地址 = %pn", (a + 1)); // 0092FDD8 数组第二个元素的地址 printf("第二个元素地址的大小 = %dn", sizeof(a + 1)); // 4 printf("第二个元素地址的strlen = %dn", strlen(a + 1)); // 1 printf("下标访问:第二个元素地址 = %pn", &a[0] + 1); // 0092FDD8 printf("下标访问:第二个元素地址的大小 = %dn", sizeof(&a[0] + 1)); // 4 printf("下标访问:第二个元素地址的strlen = %dn", strlen(&a[0] + 1)); // 1 printf("第二个元素值 = %dn", a[1]); // 2 printf("第二个元素大小 = %dn", sizeof(a[1])); // 4 // printf("第二个元素值的strlen = %dn", strlen(a[1])); // 发生异常 //字符数组 printf("字符数组 char arr1[] = { 'a','b','c','d','e','f' }; n"); char arr1[] = { 'a','b','c','d','e','f' }; printf("数组的地址 = %pn", &arr1); // 0057F77C &arr 表示的是数组的地址 printf("数组的大小 = %dn", sizeof(&arr1)); // 4 printf("数组地址的strlen = %dn", strlen(&arr1)); // 19 printf("数组的地址 = %pn", *&arr1); // 0057F77C printf("数组所占字节数 = %dn", sizeof(*&arr1)); // 6 printf("数组地址的strlen = %dn", strlen(*&arr1)); // 19 printf("第一个元素地址 = %pn", arr1); // 0057F77C 数组arr1首元素的地址 printf("数组所占字节数 = %dn", sizeof(arr1)); // 6 6个元素 * 1个字节 = 6 printf("第一个元素地址的strlen = %dn", strlen(arr1)); // 19 printf("第一个元素地址 = %pn", (arr1 + 0)); // 0057F77C 数组首元素的地址 printf("第一个元素地址的大小 = %dn", sizeof(arr1 + 0)); // 4 printf("第一个元素地址的strlen = %dn", strlen(arr1 + 0)); // 19 printf("下标访问:第一个元素地址 = %pn", &arr1[0]); // 0057F77C printf("下标访问:第一个元素地址的大小 = %dn", sizeof(&arr1[0])); // 4 printf("下标访问:第一个元素地址的strlen = %dn", strlen(&arr1[0])); // 19 printf("第一个元素值 = %cn", *arr1); // a 解引用:解析出数组首元素地址中,存放的值 printf("第一个元素值的大小 = %dn", sizeof(*arr1)); // 1 // printf("第一个元素值的strlen = %dn", strlen(*arr1)); // 异常 printf("数组所有4个元素之后的地址 = %pn", (&arr1 + 1)); // 0057F782 printf("此地址的大小 = %dn", sizeof(&arr1 + 1)); // 4 printf("此地址的strlen = %dn", strlen(&arr1 + 1)); // 13 printf("第二个元素地址 = %pn", (arr1 + 1)); // 0057F77D 数组第二个元素的地址 printf("第二个元素地址的大小 = %dn", sizeof(arr1 + 1)); // 4 printf("第二个元素地址的strlen = %dn", strlen(arr1 + 1)); // 18 printf("下标访问:第二个元素地址 = %pn", &arr1[0] + 1); // 0057F77D printf("下标访问:第二个元素地址的大小 = %dn", sizeof(&arr1[0] + 1)); // 4 printf("下标访问:第二个元素地址的strlen = %dn", strlen(&arr1[0] + 1)); // 18 printf("第二个元素值 = %cn", arr1[1]); // b printf("第二个元素大小 = %dn", sizeof(arr1[1])); // 1 // printf("第二个元素值的strlen = %dn", strlen(arr1[1])); // 发生异常 //字符数组 printf("字符数组 char arr2[] = "abcdef"; n"); char arr2[] = "abcdef"; printf("数组的地址 = %pn", &arr2); // 0107F79C &arr 表示的是数组的地址 printf("数组的大小 = %dn", sizeof(&arr2)); // 4 printf("数组地址的strlen = %dn", strlen(&arr2)); // 6 printf("数组的地址 = %pn", *&arr2); // 0107F79C printf("数组所占字节数 = %dn", sizeof(*&arr2)); // 7 printf("数组地址的strlen = %dn", strlen(*&arr2)); // 6 printf("第一个元素地址 = %pn", arr2); // 0107F79C 数组arr2首元素的地址 printf("数组所占字节数 = %dn", sizeof(arr2)); // 7 6个元素 * 1个字节 + ' ' = 7 printf("第一个元素地址的strlen = %dn", strlen(arr2)); // 6 printf("第一个元素地址 = %pn", (arr2 + 0)); // 0107F79C 数组首元素的地址 printf("第一个元素地址的大小 = %dn", sizeof(arr2 + 0)); // 4 printf("第一个元素地址的strlen = %dn", strlen(arr2 + 0)); // 6 printf("下标访问:第一个元素地址 = %pn", &arr2[0]); // 0107F79C printf("下标访问:第一个元素地址的大小 = %dn", sizeof(&arr2[0])); // 4 printf("下标访问:第一个元素地址的strlen = %dn", strlen(&arr2[0])); // 6 printf("第一个元素值 = %cn", *arr2); // a 解引用:解析出数组首元素地址中,存放的值 printf("第一个元素值的大小 = %dn", sizeof(*arr2)); // 1 // printf("第一个元素值的strlen = %dn", strlen(*arr2)); // 异常 printf("数组所有4个元素之后的地址 = %pn", (&arr2 + 1)); // 0107F7A3 printf("此地址的大小 = %dn", sizeof(&arr2 + 1)); // 4 printf("此地址的strlen = %dn", strlen(&arr2 + 1)); // 12 printf("第二个元素地址 = %pn", (arr2 + 1)); // 0107F79D 数组第二个元素的地址 printf("第二个元素地址的大小 = %dn", sizeof(arr2 + 1)); // 4 printf("第二个元素地址的strlen = %dn", strlen(arr2 + 1)); // 5 printf("下标访问:第二个元素地址 = %pn", &arr2[0] + 1); // 0107F79D printf("下标访问:第二个元素地址的大小 = %dn", sizeof(&arr2[0] + 1)); // 4 printf("下标访问:第二个元素地址的strlen = %dn", strlen(&arr2[0] + 1)); // 5 printf("第二个元素值 = %cn", arr2[1]); // b printf("第二个元素大小 = %dn", sizeof(arr2[1])); // 1 // printf("第二个元素值的strlen = %dn", strlen(arr2[1])); // 发生异常 // 字符数组 //字符数组 printf("字符数组 char *p = "abcdef"; n"); char* p = "abcdef"; printf("数组的地址 = %pn", &p); // 0108F968 &arr 表示的是数组的地址 printf("数组的大小 = %dn", sizeof(&p)); // 4 printf("数组地址的strlen = %dn", strlen(&p)); // 3 (每次的值都不固定) printf("数组的地址 = %pn", *&p); // 00A67B58 printf("数组所占字节数 = %dn", sizeof(*&p)); // 4 printf("数组地址的strlen = %dn", strlen(*&p)); // 6 printf("第一个元素地址 = %pn", p); // 00A67B58 数组p首元素的地址 printf("数组所占字节数 = %dn", sizeof(p)); // 4 ? printf("第一个元素地址的strlen = %dn", strlen(p)); // 6 printf("第一个元素地址 = %pn", (p + 0)); // 00A67B58 数组首元素的地址 printf("第一个元素地址的大小 = %dn", sizeof(p + 0)); // 4 printf("第一个元素地址的strlen = %dn", strlen(p + 0)); // 6 printf("下标访问:第一个元素地址 = %pn", &p[0]); // 00A67B58 printf("下标访问:第一个元素地址的大小 = %dn", sizeof(&p[0])); // 4 printf("下标访问:第一个元素地址的strlen = %dn", strlen(&p[0])); // 6 printf("第一个元素值 = %cn", *p); // a 解引用:解析出数组首元素地址中,存放的值 printf("第一个元素值的大小 = %dn", sizeof(*p)); // 1 // printf("第一个元素值的strlen = %dn", strlen(*p)); // 异常 printf("数组所有4个元素之后的地址 = %pn", (&p + 1)); // 0108F96C printf("此地址的大小 = %dn", sizeof(&p + 1)); // 4 printf("此地址的strlen = %dn", strlen(&p + 1)); // 8 (每次的值都不固定) printf("第二个元素地址 = %pn", (p + 1)); // 00A67B59 数组第二个元素的地址 printf("第二个元素地址的大小 = %dn", sizeof(p + 1)); // 4 printf("第二个元素地址的strlen = %dn", strlen(p + 1)); // 5 printf("下标访问:第二个元素地址 = %pn", &p[0] + 1); // 00A67B59 printf("下标访问:第二个元素地址的大小 = %dn", sizeof(&p[0] + 1)); // 4 printf("下标访问:第二个元素地址的strlen = %dn", strlen(&p[0] + 1)); // 5 printf("第二个元素值 = %cn", p[1]); // b printf("第二个元素大小 = %dn", sizeof(p[1])); // 1 // printf("第二个元素值的strlen = %dn", strlen(p[1])); // 发生异常 //二维数组 printf("二维数组 int as[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} }; n"); int as[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} }; printf("%dn", sizeof(as)); // 48 as:数组as首元素的地址 printf("%dn", sizeof(as[0][0]));//4 printf("%dn", sizeof(as[0])); //16 printf("%dn", sizeof(as[0] + 1));//4 printf("%dn", sizeof(*(as[0] + 1))); //4 printf("%dn", sizeof(as + 1)); // 4 printf("%dn", sizeof(*(as + 1))); //16 printf("%dn", sizeof(&as[0] + 1));// 4 printf("%dn", sizeof(*(&as[0] + 1)));// 16 printf("%dn", sizeof(*as)); // 16 printf("%dn", sizeof(as[3]));// 16 return 0; }
- code示例



