類型雙關

維基百科,自由的百科全書

類型雙關計算機科學的術語,指任何編程技術能顛覆或者繞過一門程序設計語言類型系統,以達成在形式語言內部難以甚至不可能實現的效果。

C語言C++語言,語法結構如類型轉換union,以及C++增加的reinterpret_cast運算符,用於實現類型雙關。

Pascal語言使用recordsvariants來按照多種方法處理特定數據類型。

Socket例子[編輯]

Berkeley sockets使用類型雙關來處理IP位址。函數bind綁定一個位初始化的套接字到一個IP位址,其聲明如下:

int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);

bind函數通常如此使用:

struct sockaddr_in sa = {0};
int sockfd = ...;
sa.sin_family = AF_INET;
sa.sin_port = htons(port);
bind(sockfd, (struct sockaddr *)&sa, sizeof sa);

這是因為struct sockaddr_instruct sockaddr有相同的內存布局。兩個類型的指針可以互相轉換。

浮點例子[編輯]

類型雙關不僅限於struct。對於浮點數,判斷其是否為負值:

bool is_negative(float x) {
    return x < 0.0;
}

假定浮點比較的代價高昂,並假定浮點數用IEEE 754標準,就可以用類型雙關獲取浮點數的符號位(sign bit)做整型比較:

bool is_negative(float x) {
    unsigned int *ui = (unsigned int *)&x;
    return *ui & 0x80000000;
}

注意有一些特例,如x負0,前一種實現返回false而第二種實現返回true.

這樣的實現適合於實時計算而又不能被優化實現的情形。注意把所有假定均寫為注釋記錄下來,並寫入靜態斷言(static assertions)驗證可移植期望是否滿足。雷神之錘III競技場遊戲用此方法實現平方根倒數速算法

使用union[編輯]

為了遵循C99/C++的嚴格別名規則,可以使用union:[1]

bool is_negative(float x) {
    union {
        unsigned int ui;
        float d;
    } my_union = { .d = x };
    return my_union.ui & 0x80000000;
}


GCC編譯器支持這樣的語言擴展。[2]

其他的類型雙關,見數組步長

參考文獻[編輯]

  1. ^ ISO/IEC 9899:1999 s6.5/7
  2. ^ GCC: Non-Bugs. [2017-11-20]. (原始內容存檔於2021-03-25). 

外部連結[編輯]