目录
- 指针
- C语言指针笔记
- 用指针指向一块地址
- 指针变量指向数组
- 指针变量和常量指针
- 函数指针
- 注意事项
指针
- 基本概念
指针定义:使用符号声明指针变量,例如int * ptr;。
指针初始化:指针变量可以通过赋值操作初始化为某个变量的地址,例如ptr = & num;。
指针访问:通过符号可以访问指针所指向的内存地址上的值,例如*ptr。
空指针:指针变量可以被赋值为NULL,表示指向空地址。
指针算术:指针可以进行加法和减法运算,用于访问数组中的元素或者在内存中进行偏移操作。 - 指针和数组
指针与数组名:数组名本身就是一个指针,可以用于访问数组的首地址。
指针和数组的关系:指针可以用于遍历数组,通过指针算术实现数组元素的访问和操作。
指针数组:可以创建指针的数组,每个元素都是指向特定类型的指针。 - 指针和函数
指针作为函数参数:可以将指针作为参数传递给函数,以便在函数内部修改原始数据。
指针作为函数返回值:函数可以返回指针,以便将函数内部的动态分配内存传递给调用者。 - 动态内存分配
动态内存分配函数:malloc()、calloc()和realloc()函数用于在运行时动态分配内存空间。 - 释放内存:使用free()函数释放之前动态分配的内存空间。
C语言指针笔记
## 指针的基本概念
- 指针是一个变量,用于存储内存地址。
- 通过指针,可以访问和操作内存中的数据。
## 声明和初始化指针
- 声明指针时,使用`*`符号来表示指针类型。
- 初始化指针时,可以使用`&`运算符获取变量的地址。
```c
int *ptr; // 声明一个整型指针
int num = 10;
ptr = # // 将ptr指向num的地址
各种指针的定义
既然指针在操作系统中都是用8个字节表示一个地址,那么为什么定义的时候需要声明什么类型的指针变量呢?
声明类型以后,在p+1的时候,编译器才知道应该跨越多少字节(如指向
a[1]
,a[1][1]
的指针在加1后偏移的地址不同)才能指向下一个变量的地址。
用指针指向一块地址
注意要把常量转换成无符号整形指针的数据类型,一般还要加 volatile 防止被优化
volatile unsigned int *p = (volatile unsigned int *)0x000051EF;
printf("p = 0x%p\n", p);
指针变量指向数组
C语言中,数组名代表数组中首元素的地址
p = &a[0]; //p的值是a[0]的地址
p = a; //p的值是数组a首元素(即a[0])的地址
指针变量和常量指针
int array[3] = {1, 2, 3};
int *p = array;
for (int i = 0; i < 3; i++) {
printf("%d", *p++); //指针变量可以改变,指向数组下一个元素的地址
printf("%d", *array++); //错误,array数组名为常量指针,指向固定地址
}
函数指针
函数地址(函数名就是函数地址)
如果在程序中定义了一个函数,在编译时,编译系统为函数代码分配了一段存储空间,这段存储空间的起始地址(又称入口地址)称为这个函数的指针。
定义一个函数指针变量
int getData(int, int);
int (*p)(int, int);
//如果不加括号 int *p(int a, int b); 括号优先级更高,代表一个返回值为整形指针的函数,所以必须加括号
p = getData; //函数指针指向函数,函数名就是函数地址
int data;
data = (*p)(1,2); //*表示取值运算符,调用p指向的函数
案例:回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。
#include<stdio.h>
int Callback_1(int x) // Callback Function 1
{
printf("Hello, this is Callback_1: x = %d ", x);
return 0;
}
int Callback_2(int x) // Callback Function 2
{
printf("Hello, this is Callback_2: x = %d ", x);
return 0;
}
int Callback_3(int x) // Callback Function 3
{
printf("Hello, this is Callback_3: x = %d ", x);
return 0;
}
int Handle(int y, int (*Callback)(int))
{
printf("Entering Handle Function. ");
Callback(y);
printf("Leaving Handle Function. ");
}
int main()
{
int a = 2;
int b = 4;
int c = 6;
printf("Entering Main Function. ");
Handle(a, Callback_1);
Handle(b, Callback_2);
Handle(c, Callback_3);
printf("Leaving Main Function. ");
return 0;
}
运行结果:
Entering Main Function.
Entering Handle Function.
Hello, this is Callback_1: x = 2
Leaving Handle Function.
Entering Handle Function.
Hello, this is Callback_2: x = 4
Leaving Handle Function.
Entering Handle Function.
Hello, this is Callback_3: x = 6
Leaving Handle Function.
Leaving Main Function.
可以看到,并不是直接把int Handle(int (*Callback)()) 改成 int Handle(int (*Callback)(int)) 就可以的,而是通过另外增加一个参数来保存回调函数的参数值,像这里 int Handle(int y, int (*Callback)(int)) 的参数 y。同理,可以使用多个参数的回调函数。
注意事项
指针的使用需要注意空指针和野指针的情况,避免访问无效内存。
在进行指针操作时,确保指针指向有效的内存地址。
熟练掌握指针的概念和操作,能够灵活运用指针来处理各种编程任务。