计算机科学

首页 > 计算机科学

类型双关

2018-08-31 09:32:03     所属分类:程序架构

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

C语言与C++语言,语法结构如类型转换与union,以及C++增加的reinterpret_cast运算符,用于实现类型双关。

Pascal语言使用records与variants来按照多种方法处理特定数据类型。

目录

  • 1 Socket例子
  • 2 浮点例子
  • 3 使用union
  • 4 Pascal
  • 5 C#
    • 5.1 Pointers
    • 5.2 Struct unions
    • 5.3 Raw CIL code
  • 6 参考文献
  • 7 外部链接

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

外部链接

  • Section of the GCC manual on -fstrict-aliasing, which defeats some type punning
  • Defect Report 257 to the C99 standard, incidentally defining "type punning" in terms of union, and discussing the issues surrounding the implementation-defined behavior of the last example above
  • Defect Report 283 on the use of unions for type punning

上一篇:保留字
相关推荐