C語言中文網 目錄
首頁 > 編程筆記 > C語言筆記 > 指針 閱讀:1,162

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) );



精美而實用的網站,提供C語言、C++、STL、Linux、Shell、Java、Go語言等教程,以及socket、GCC、vi、Swing、設計模式、JSP等專題。

Copyright ?2011-2018 biancheng.net, 陜ICP備15000209號

底部Logo
极速pk10开户