C 语言学习七:指针
指针
- 指针与地址
- 指针的声明和初始化
- 指针的解引用
- 指针的比较
- 指针和数组
- 指针数组
- 指针和动态内存分配
- 指针与函数参数
- 指针作为函数参数
- 二级指针
- 指向函数的指针
指针与地址
指针的声明和初始化
int variable = 42;
int *ptr = &variable;
//间接访问
int value = *ptr; // value 等于 x 的值,即 42
char str[] = "Hello"; // 字符串数组
const char* ptr = "World"; // 字符串指针
-
空指针:未指向任何对象的指针
int *ptr = NULL;
指针的解引用
通过指针可以访问或修改其指向的变量的值,通过使用解引用操作符 * 完成。
int value = *ptr; // 通过指针获取变量的值
*ptr = 10; // 通过指针修改变量的值
指针的比较
指针可以进行大小比较,但要注意指针比较的是地址而不是指向的值
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
int arr[5] = { 1, 2, 3, 4, 5 };
int* ptr1 = arr;
int* ptr2 = arr + 2;
printf("*ptr1=%d\n", *ptr1);
printf("*ptr2=%d\n", *ptr2);
printf("ptr1=%d\n", ptr1);
printf("ptr2=%d\n", ptr2);
if (ptr1 < ptr2) {
// 执行此处代码
}
return 0;
}
指针和数组
指针可以进行算术运算,例如指针加法和指针减法。在数组遍历和动态内存管理中非常有用(区分开地址和值的变化)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
int arr[5] = { 1, 2, 3, 4, 5 };
int* ptr = arr;
// 指针加法
ptr = ptr + 2; // 移动两个元素
*ptr = *ptr - 1; //值变化
printf("*ptr=%d", *ptr);
// 现在 ptr 指向 arr[1]
return 0;
}
指针数组
-
定义: 指针数组是一个数组,其元素都是指针
int *ptrArray[5]; // 声明一个包含 5 个指针的数组
-
初始化:指针数组的每个元素必须指向相同类型或相同结构的数据
int a = 5, b = 10, c = 15; int *ptrArray[3] = {&a, &b, &c}; // 初始化指针数组
-
使用:当需要一次性操作多个相关的指针,而这些指针的数量可能在运行时发生变化时,使用指针数组能够更方便地管理这些指针。
指针和动态内存分配
malloc、calloc、realloc 和 free 等函数用于动态内存分配和释放,返回的是指向动态分配内存的指针。
int *dynamicArray = (int *)malloc(5 * sizeof(int));
指针与函数参数
指针作为函数参数
-
函数可以接受指针作为参数,允许函数修改调用者提供的变量的值
void modifyValue(int *ptr) { *ptr = 100; } int main() { int value = 42; modifyValue(&value); // 此时 value 的值变为 100 }
-
同样的也可以修改数组的元素
void modifyArray(int *arr, int size) { for (int i = 0; i < size; ++i) { arr[i] *= 2; } } int main() { int arr[] = {1, 2, 3, 4, 5}; modifyArray(arr, 5); //数组名就是数组的首地址 // 此时 arr 变为 {2, 4, 6, 8, 10} }
二级指针
以动态分配内存为例
当传递一个指针给函数时,传递的是指针的拷贝。如果在函数内部分配了新的内存,并将这个新内存的地址赋给传入的指针,这对于调用者的指针没有影响。为了解决这个问题,可以传递一个指针的指针,也就是二级指针
void allocateMemory(int **ptr) {
*ptr = (int *)malloc(sizeof(int));
**ptr = 42;
}
int main() {
int *dynamicValue;
allocateMemory(&dynamicValue);
// 此时 dynamicValue 指向了动态分配的内存,其值为 42
}
int **ptr 表示一个指向指针的指针。这是为了能够在函数内部修改指针的值。
指向函数的指针
-
定义函数指针:函数指针的声明形式类似于函数声明,只需在函数名前面加上指针类型,例如
int (*ptr)(int, int);
表示 ptr 是一个指向接受两个整数参数并返回整数的函数的指针 -
初始化函数指针:
ptr = &add;
其中 add 是一个函数,ptr 就指向了这个函数 -
用途:
回调函数: 当你需要在某个地方注册一个函数,以便在特定事件发生时调用它时,函数指针就非常有用。例如,你可能有一个事件处理器,允许用户注册一个函数,然后在某个事件发生时调用该函数// 使用函数指针实现回调 void eventHandler(void (*callback)(int)) { // 做一些操作 int data = 42; // 调用注册的回调函数 callback(data); } // 注册的回调函数 void myCallback(int value) { printf("Callback called with value: %d\n", value); } int main() { // 在事件处理器中注册回调函数 eventHandler(myCallback); return 0; }