### 指针 指针变量是用来记录地址数据的。 只有记录有效地址的指针才可以使用。 声明指针变量时需要在变量名称前加*。 /* 指针声明演示 */ #include <stdio.h> int main(){ int num = 0; int *p_num; // 声明指针变量 p_num = &num; // 给指针赋值 *p_num = 10; printf("num = %d\n", num); return 0; } 有效指针前加*可以表示它所捆绑的存储区。 指针变量也分类型,不同类型的指针适合与不同类型的存储区捆绑。 可以在一条语句里声明多个同类型指针变量,这个时候要在每个指针变量名称前单独加* /* 指针变量演示 */ #include <stdio.h> int main(){ int *p1, *p2; return 0; } ### 野指针 没有捆绑地址的指针分为两类: * 1. 空指针,里面记录空地址(NULL),这个地址的数值就是0。 * 2. 其它没有捆绑的指针都叫做野指针。 程序中禁止出现野指针。 所有指针变量必须初始化。 指针初始化的时候*没有参与赋值过程。 ### 指针的运算 一个指针可以在不同的时候和不同的存储区捆绑,这个时候指针代表了存储区的某种特征。 如果指针和数组里的第一个存储区捆绑,就可以通过这个指针找到数组里的每个存储区。 这个时候可以认为指针间接捆绑了数组里的每个存储区。 直接在这种指针的后面加下标就可以表示数组里的某个存储区。 地址数据只能参与如下的几个计算过程: * 地址 + 整数 * 地址 - 整数 * 地址 - 地址 地址数据加减整数N实际上加减的是n个捆绑存储的大小。 /* 指针演示 */ #include <stdio.h> int main(){ int arr[] = {1, 2, 3, 4, 5}; int num = 0; int *p_arr = arr; for (num = 0;num <= 4;num++){ printf("%d ", arr[num]); printf("%d ", p_arr[num]); } printf("\n"); printf("arr + 3 = %p, arr = %p\n", arr+3, arr); return 0; } 数组里第一个存储区的地址加下标可以得到下标对应存储区的地址。 *(arr + num),这个写法也可以代表下标为num的存储区。 地址减地址的结果是一个整数,这个整数代表两个地址之间包含的捆绑存储区个数。 /* 指针演示 */ #include <stdio.h> int main(){ int arr[] = {1, 2, 3, 4, 5}; int *p_arr = arr; for (p_arr = arr;p_arr <= arr + 4;p_arr++){ printf("%d ", *p_arr); } printf("\n"); return 0; } ### const关键字 声明指针变量的时候可以使用const关键字。 如果const关键字写在指针声明的类型名称前就表示不可以通过这个指针对捆绑存储区做赋值,但是可以对指针本身做赋值。 /* const关键字演示 */ #include <stdio.h> int main(){ int num = 0; const int *p_num = &num; // *p_num = 10; // 编译出错,无法修改捆绑存储区的值 p_num = NULL; // 可以设置指针为空指针 return 0; } 如果const关键字写在指针变量名称前就表示不可以对这种指针做赋值,但是可以通过这个指针对它捆绑的存储区做赋值。 /* const关键字演示 */ #include <stdio.h> int main(){ int num = 0; int * const p_num = &num; // p_num = NULL; 错误 *p_num = 10; return 0; } ### 无类型指针 可以在声明指针变量的时候使用void作为类型名称,这种指针叫做无类型指针。 这种指针可以和任意类型的存储区捆绑。 但是这种类型的指针,不能通过指针知道它所捆绑的存储区类型是啥。 /* 无类型指针演示 */ #include <stdio.h> int main(){ char ch = 'u'; int num = 56; float fnum = 6.5f; void *p_v = NULL; p_v = &ch; p_v = &num; p_v = &fnum; return 0; } 不应该在无类型指针前直接加*,也不应该用无类型指针进行加减计算,因为这些操作都是依赖于存储区类型的,因此这些操作是不允许的。 使用无类型指针前,必须先强制类型转换成有类型指针。 /* 无类型指针演示 */ #include <stdio.h> int main(){ char ch = 'u'; void *p_v = NULL; p_v = &ch; printf("%c\n", *(char *)p_v); return 0; } 无类型指针通常作为形式参数使用。 ### 数组形式参数 所有的跨函数使用存储区都是通过指针实现的。 数组做形式参数的时候,真正的形式参数都是指针。 /* 指针形式参数演示 */ #include <stdio.h> void print(const int *p_arr, int size){ int num = 0; for (num = 0;num <= size - 1;num++){ printf("%d ", *(p_arr + num)); } printf("\n"); } int main(){ int arr[] = {1, 2, 3, 4, 5}; print(arr, 5); return 0; } 指针形式参数前能加const关键字就尽量加上。 ### 指针返回值 被调用函数使用一个存储区地址做返回值,这个时候就需要提供一个指针类型存储区来存放这个返回值。 采用这种方法可以让调用函数使用被调用函数的存储区。 不可以把非静态局部变量的地址作为返回值使用。 /* 指针演示 */ #include <stdio.h> int *read(void){ static int num = 0; printf("请输入一个数字:"); scanf("%d", &num); return &num; } int main(){ int *p_res = NULL; p_res = read(); printf("%d\n", *p_res); return 0; }