类型双关

维基百科,自由的百科全书

类型双关计算机科学的术语,指任何编程技术能颠覆或者绕过一门程序设计语言類型系統,以达成在形式语言内部难以甚至不可能实现的效果。

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

外部链接[编辑]