3.7 KiB
C 语言中的空指针
最后更新于 2020 年 7 月 27 日
我们在 C 语言的指针基础一章中了解到,如果一个指针是指向int或(int *)的指针类型,那么它只能保存int类型变量的地址。如果我们将一个float变量的地址分配给一个指向int的指针类型的指针,这将是不正确的。但是void指针是这个规则的例外。一个void指针可以指向任何数据类型的变量。以下是void指针的语法。
语法: void *vp;
让我们举个例子:
void *vp;
int a = 100, *ip;
float f = 12.2, *fp;
char ch = 'a';</pre>
这里vp是一个void指针,所以你可以给它分配任何类型变量的地址。
vp = &a; // ok
vp = ip; // ok
vp = fp; // ok
ip = &f; // wrong since type of ip is pointer to int
fp = ip; // wrong since type of fp is pointer to float</pre>
void指针可以指向任何数据类型的变量,void指针可以被分配给任何类型的指针。
取消引用空指针
我们不能仅仅使用间接(*)操作符来取消引用一个空指针。例如:
void *vp;
int a = 100;
vp = &a;
printf("%d", *vp); // wrong
它根本不是那样工作的!。在取消引用空指针之前,必须将其类型转换为适当的指针类型。让我告诉你我的意思。
例如:在上面的片段中void指针vp指向整数变量 a 的地址,所以在这种情况下vp充当指向int或(int *)的指针。因此在这种情况下正确的类型是(int*)。
(int *)vptr
现在vptr的类型暂时从void指针变为指向int或(int*)的指针,我们已经知道如何去引用指向int的指针,只需在它前面加上间接操作符(*)
*(int *)vptr
**注意:**类型转换暂时改变vp的类型,直到表达式求值,程序中的其他地方vp仍然是一个空指针。
下面的程序演示了如何取消引用void指针。
#include<stdio.h>
#define SIZE 10
int main()
{
int i = 10;
float f = 2.34;
char ch = 'k';
void *vptr;
vptr = &i;
printf("Value of i = %d\n", *(int *)vptr);
vptr = &f;
printf("Value of f = %.2f\n", *(float *)vptr);
vptr = &ch;
printf("Value of ch = %c\n", *(char *)vptr);
// signal to operating system program ran fine
return 0;
}
预期输出:
Value of i = 10
Value of f = 2.34
Value of ch = k
空指针中的指针算法
我想提的另一个重要的点是关于带 void 指针的指针算法。在 void 指针中应用指针算法之前,请确保首先提供正确的类型转换,否则可能会得到未接受的结果。
考虑以下示例:
int one_d[5] = {12, 19, 25, 34, 46}, i;
void *vp = one_d;
printf("%d", one_d + 1); // wrong
这里我们已经将数组的名称one_d分配给了空指针vp。由于one_d的基本类型是指向int或(int*)的指针,因此空指针vp的作用类似于指向int或(int*)的指针。所以合适的类型是(int*)。
int one_d[5] = {12, 19, 25, 34, 46}, i;
void *vp = one_d;
printf("%d", (int *)one_d + 1); // correct
下面的程序演示了 void 指针中的指针算法。
#include<stdio.h>
#define SIZE 10
int main()
{
int one_d[5] = {12, 19, 25, 34, 46}, i;
void *vp = one_d;
for(i = 0; i < 5; i++)
{
printf("one_d[%d] = %d\n", i, *( (int *)vp + i ) );
}
// signal to operating system program ran fine
return 0;
}
预期输出:
one_d[0] = 12
one_d[1] = 19
one_d[2] = 25
one_d[3] = 34
one_d[4] = 46
void 指针在动态内存分配中被广泛使用,我们将在下面讨论。