• C语言指针的初始化以及什么是空指针和void指针

    指针(pointer)是对数据对象或函数的一种引用。指针有多种用途,例如定义“传址调用”函数,它还可以实现动态数据结构,例如链表和树。接下来我们来介绍如何初始化一个指针。

    指针初始化

    具有动态存储周期的指针变量,开始是没有定义值的,除非它们在声明的同时进行了显式地初始化。在语句块内定义的所有变量,只要没有被声明为 static,就具有动态存储周期。所有指针在定义时如果没有初始化,则空指针默认作为它们的初始化值。

    可以用下列方式来初始化一个指针:
    (1) 一个空指针常量。
    (2) 指向相同类型的指针,或者指向具有较少限定符修饰的相同类型。
    (3) 如果需初始化的指针不是函数指针,可以使用 void 指针进行初始化(同上,需初始化的指针可以是指向具有更多限定符类型的指针)。

    指针如果不具有动态存储周期,则必须用常量表达式来初始化,例如取址运算的结果,或者使用数组或函数的名称。

    当初始化指针时,除非是上面说明的情况,否则不会发生隐式类型转换。然而,可以将一个指针值显式地转换成另一个指针类型。例如,若想一个字节接着一个字节地读取对象,可以将其地址转换成 char 指针,指向此对象的第一个字节:

    double x = 1.5;
    char *cPtr = &x;          // 错误:类型不匹配;没有隐式转换
    char *cPtr = (char *)&x;  // 正确:cPtr指向x的第一个字节

    所有指针在定义时如果没有初始化,则空指针默认作为它们的初始化值。如果需初始化的指针不是函数指针,可以使用 void 指针进行初始化。那么什么是空指针和 void 指针呢?

    空指针

    当把一个空指针常量转换为指针类型时,所得到的结果就是空指针(null pointer)空指针常量(null pointer constant)是一个值为 0 的整数常量表达式,或者是一个 void* 类型的表达式。在头文件 stdlib.h、stdio.h 以及其他头文件中,宏 NULL 被定义为空指针常量。

    空指针有别于其他指向对象或函数的有效指针。因此,当返回值为指针的函数出现执行失败的情况时,它通常会使用空指针作为返回值。标准函数 fopen()正是这样的一个例子,如果在指定的模式下打开某文件失败时,该函数会返回一个空指针。

    #include <stdio.h>
    /* ... */
    FILE *fp = fopen( "demo.txt", "r" );
    if ( fp == NULL )           // 也可以被写成:if ( !fp )
    {
      // 错误:无法打开demo.txt文件进行读取
    }

    如果有必要的话,空指针会被隐式地转换成其他指针类型,以进行赋值运算或者是进行 == 或 != 的比较运算。因此,上述例子不需要使用转型运算符。

    void 指针

    指向 void 的指针,或者简称为 void 指针(void pointer),是类型为 void* 的指针。因为没有对象类型是 void,所以 void* 被称为万能指针类型。换句话说,void 指针可以代表任何对象的地址,但不代表该对象的类型。若想获取内存中的对象,必须先把 void 指针转换为合适的对象指针。

    若想声明一个可以接收任何类型指针参数的函数,可以将所需的参数设定为指向 void 的指针。当调用这样的函数时,编译器会隐式地将对象指针参数转换成 void 指针。常见的例子如标准函数 memset(),它被声明在头文件 string.h 中,其原型如下:

    void *memset( void *s, int c, size_t n );

    函数 memset()将 c 的值赋值到从地址 s 开始的 n 个内存字节中。例如,下面的函数调用会将 0 值赋值到结构变量 record 中的每个字节:

    struct Data { /* ... */ } record;
    memset( &record, 0, sizeof(record) );

    实参 &record 具有 struct Data* 类型。在函数调用中,实参被转换成形参类型,即 void*。

    编译器会在必要的地方把 void 指针转换为对象指针。例如,在下面的语句中,函数 malloc()返回一个 void 指针,它的值是已分配内存的语句块的地址。这样的赋值操作会把 void 指针转换成 int 指针:

    int *iPtr = malloc( 1000 * sizeof(int) );

更多...

加载中...