3

我正在查看 Barnyard2 的 sf_ip.h源代码。我不了解 sfip_t stuct,特别是联合块。

typedef struct _ip {
    int family;
    int bits;

    /* see sfip_size(): these address bytes
* must be the last field in this struct */
    union
    {
        u_int8_t u6_addr8[16];
        u_int16_t u6_addr16[8];
        u_int32_t u6_addr32[4];
// u_int64_t u6_addr64[2];
    } ip;
    #define ip8 ip.u6_addr8
    #define ip16 ip.u6_addr16
    #define ip32 ip.u6_addr32
// #define ip64 ip.u6_addr64
} sfip_t;

为什么使用数组?我试图寻找文档,但谷歌一直没有运气。谁能解释一下这里正在做什么?

4

1 回答 1

3

C 中的联合对其所有元素使用相同的内存块。这与结构不同,其中元素在内存中是连续的。

因此,如果您的变量从内存位置开始,那么 whilestruct {int x; int y;}将被布置0x40000000

           +-------------+
0x40000000 | x (4 bytes) |
           +-------------+
0x40000004 | y (4 bytes) |
           +-------------+

一个相关的union {int x; int y;}存在是这样的:

Address
           +-------------+-------------+
0x40000000 | x (4 bytes) | y (4 bytes) |
           +-------------+-------------+

换句话说,它一次只能用于件事,从技术上讲,它是y您上次用于x设置变量时使用的未定义行为 - 尽管在这种情况下,您很可能会发现它会起作用,因为这两个可能性是同一类型。

在您的特定情况下,您具有以下内存布局(假设您的变量位于0x40000000):

           +--------------+--------------+--------------+
0x40000000 | u6_addr8[ 0] |              |              |
           +--------------+ u6_addr16[0] |              |
0x40000001 | u6_addr8[ 1] |              |              |
           +--------------+--------------+ u6_addr32[0] |
0x40000002 | u6_addr8[ 2] |              |              |
           +--------------+ u6_addr16[1] |              |
0x40000003 | u6_addr8[ 3] |              |              |
           +--------------+--------------+--------------+
0x40000004 | u6_addr8[ 4] |              |              |
           +--------------+ u6_addr16[2] |              |
0x40000005 | u6_addr8[ 5] |              |              |
           +--------------+--------------+ u6_addr32[1] |
0x40000006 | u6_addr8[ 6] |              |              |
           +--------------+ u6_addr16[3] |              |
0x40000007 | u6_addr8[ 7] |              |              |
           +--------------+--------------+--------------+
0x40000008 | u6_addr8[ 8] |              |              |
           +--------------+ u6_addr16[4] |              |
0x40000009 | u6_addr8[ 9] |              |              |
           +--------------+--------------+ u6_addr32[2] |
0x4000000a | u6_addr8[10] |              |              |
           +--------------+ u6_addr16[5] |              |
0x4000000b | u6_addr8[11] |              |              |
           +--------------+--------------+--------------+
0x4000000c | u6_addr8[12] |              |              |
           +--------------+ u6_addr16[6] |              |
0x4000000d | u6_addr8[13] |              |              |
           +--------------+--------------+ u6_addr32[3] |
0x4000000e | u6_addr8[14] |              |              |
           +--------------+ u6_addr16[7] |              |
0x4000000f | u6_addr8[15] |              |              |
           +--------------+--------------+--------------+

假设您了解您的特定 C 实现如何布置各种类型,这提供了一种以不同方式引用相同数据的方法。

于 2013-05-28T08:19:21.053 回答