最近更新: 2007-07-11

舊程式碼中的 void* 轉型

前一陣子,為了說明《程式語言中的介面》,我把大約八、九年前寫的 C 語言程式碼翻了出來。編譯的時候出現錯誤訊息,顯示我用了不被允許的轉型動作,即 (void*)。雖然心裡嘀咕了一下,不過還是很快地改成完整的轉型語法 (也更冗長),將之用於文章範例。

這幾天抽空檢視了一下那些舊程式碼,才發現不是程式碼的問題,而是我用錯編譯器了。我的編輯器 PSPad 設定 C/C++ 文件呼叫的編譯器是 g++ (C++ compiler) ,而不是 gcc (C compiler)。而 C++ 不允許將 void* 轉型為其他型態指標。這點與 C 不同。我又測了一下舊有程式碼的 C/C++ 規範相容性。

首先看一下程式碼,《程式語言中的介面》一文中的是修改過的,而 bbslib-20010331 是原本的舊程式碼。取兩段列示於下:

/* 轉型動作1 */
tmp->striobj.length  = (void*) buffer_length; /* 舊程式碼。 */

/* 轉型動作2 */
tmp->striobj.length  = (size_t (*)(const void*)) buffer_length; /* 修改後。 */

我用 gcc 編譯器配合 -std 選項,以檢視新、舊程式碼對 C/C++ 規範的相容性。選項用法列示於下:

gcc
    -std=c89    # ANSI C 1989, 第一版 ANSI C 規範
    -ansi       # 同 -std=c89
    
    -std=gnu89  # 加上 gcc 的擴充功能,例如雙斜線注解形式
                # defaults for .c
    
    -std=c99    # ANSI C 1999, 加入 C++ 規範

    -std=gnu99  # defaults for .cc

轉型動作1 ,適用 c89,gnu89 規範,但不適用於 c99, gnu99 等新式規範。

轉型動作2 ,新、舊規範都適用。但新規範中已建議捨棄這種強制轉型動作,改用新式轉型動作。

轉型動作1 其實是我偷懶的寫法。因為 C 語言可以將 void* 自動轉型為任何指標,所以我強制轉型為 void* ,便不用輸入完整的函數指標型態宣告,而由 C 語言再次自動轉型 void* 為目標型態。至於轉型動作2 ,當然是最正式的作法了,原本就不會有問題。

樂多舊網址: http://blog.roodo.com/rocksaying/archives/3641993.html