首页 文章

什么是打字?类型惩罚如何与C中的工会一起使用?

提问于
浏览
-1

任何人都可以解释一下C中的 type punning ,并通过一个简单的示例程序演示何时出现此类问题?

我在很多网站上搜索过(甚至维基),但即便如此,我也无法理解 .

1 回答

  • 5

    Punning类型是一个广泛的概念,适用于任何具有类型系统和一点灵活性的语言,所以我使用维基百科的例子与Berkeley套接字:

    从维基百科页面:

    在Berkeley套接字界面中可以找到一个经典的类型惩罚示例 . 将已打开但未初始化的套接字绑定到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);
    

    Berkeley套接字库基本上依赖于以下事实:在C中,指向struct sockaddr_in的指针可以自由转换为指向struct sockaddr的指针;此外,两种结构类型共享相同的内存布局 . 因此,对结构字段my_addr-> sin_family(其中my_addr的类型为struct sockaddr *)的引用实际上将引用字段sa.sin_family(其中sa的类型为struct sockaddr_in) . 换句话说,套接字库使用类型punning来实现一种基本的继承形式 .

    Edit: 我没有't notice the edit where you mentioned trying Wikipedia. I think what you should take away in that case is what I say in the first sentence, namely 440321 . If you'遇到麻烦我'd say look for more examples and implementations of the strategy (maybe look at OOP in C to get a little bit more of some of the concepts involved [it'本身并不完全相同])

    Another Edit: 在我看来,也许你的意思是在工会的背景下打字,所以这里是一个来自this问题的修改例子,它询问了工会的目的(在这里向后工作):

    union RGB
    {
        uint32_t color;
    
        struct componentsTag
        {
            uint8_t r;
            uint8_t g;
            uint8_t b;
        } components;
    
    } pixel;
    
    pixel.color = 0x020406;
    uint8_t rVal = pixel.components.r; //this will equal 02
    uint8_t gVal = pixel.components.g; //this will equal 04
    uint8_t bVal = pixel.components.b; //this will equal 06
    

    这里使用类型双关语来允许访问每种颜色的单个值而无需C类型转换 . 您可能想知道这是如何工作的 . 在内存中,union占用了32位 . 当 color 设置为 pixel.color = 0x020406 行时,这些32位填充值0x020406(0x后的每对值占用8位(8 * 3 = 32位) .

    将32位拆分成部分的图表可能如下所示:

    ------------------------------
    -----| 02  | 04  | 06  |------
    ------------------------------
         |      color      |
    ------------------------------
    

    但组件的结构也占用了32位 in the same space .

    所以现在联盟内存的完整图表是:

    ------------------------------
    -----| 02  |  04  | 06  |-----
    ------------------------------
         |  r  |  g   |  b  |
    ------------------------------
    ------------------------------
         |      color       |
    ------------------------------
    

    注意 rgb 如何重叠 color . 访问 rgb 现在访问 color 的一个特定部分,它是一个8位部分 . 通常将uint32_t转换为uint8_t只会给你uint32_t的最低有效位,所以 rgb 都会变成无意义的数字 . 但正如我之前所说,此处联合被用于类型惩罚,因此标准定义的转换被规避 .

相关问题