geekdoc-python-zh/docs/overiq/053.md

3.7 KiB

C 语言中的空指针

原文:https://overiq.com/c-programming-101/void-pointers-in-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 指针在动态内存分配中被广泛使用,我们将在下面讨论。