【问题标题】:C storing 2 numbers in one byteC在一个字节中存储2个数字
【发布时间】:2011-12-16 08:36:24
【问题描述】:
u_char  ip_vhl;     /* version << 4 | header length >> 2 */

我做错了,这是怎么做到的? 你能给我举例说明如何使用这个字节来存储这两个数字吗 知道每个都是 4 位的

【问题讨论】:

    标签: c binary bit-shift


    【解决方案1】:

    如果每个数字都是 4 位,您将使用字符的最低 8 位。在许多情况下,这将是所有的位。

    这样做:

    ip_vhl = ((version & 15) << 4) | (length & 15);
    

    假设version 是你想要的高位,length 是你想要的低位。 &amp; 15 确保每个值只有 4 位。 length 值最需要这点,以避免在长度大于 15 时覆盖专用于 version 的位。十进制常量 15 将以十六进制写入(如 0xf0x0f)很多人,你觉得更干净是风格和品味的问题。

    另一种写“一个最右边 n 位设置为 1,所有其他位设置为 0 的整数”的方式是 ((1 &lt;&lt; n) - 1),因为这里是 n = 4,我们可以使用 ((1 &lt;&lt; 4) - 1),它当然会计算到15

    为了清楚起见,您的代码似乎首先将 length 划分并存储,如果您想要这样做,您应该在将其打包到单个 char 之前执行它:

    length >>= 2;  /* Convert from bytes to 32-bit words (or whatever). */
    ip_vhl = ((version & 15) << 4) | (length & 15);
    

    【讨论】:

    • 0xf 而不是 15 会更好看
    • @ThiefMaster:我猜这是品味问题……它长了一个字符。但我会编辑提及它。
    • 我找到了位掩码的十六进制清洁器,因为它与位模式非常直接对应。但这并不意味着我总是使用十六进制;-)
    【解决方案2】:

    版本 (a) 使用位域

    struct entry {
      unsigned char version : 4;
      unsigned char length  : 4;
    } ip_vhl;
    
    ip_vhl.version = version;
    ip_vhl.length = length;
    

    版本 (b) 算术

    ip_vhl = (version << 4) | (length & 0xF)
    version = ip_vhl >> 4;
    length  = ip_vhl & 0xf;
    

    【讨论】:

    • 根据标准 C99,位域是非常特定于实现的。可能不支持 _Bool 和 int(有符号和无符号)以外的类型。位域的顺序是实现定义的。它们将占用多少内存也是特定于实现的(可能会占用过多的内存)。对齐方式相同。
    • @Alex 具体用法取决于你的需要。位域非常有用。
    • 我没有说它们没有/不能有用。我只是警告说它们可能不是正确的或可移植的解决方案。
    【解决方案3】:
    ip_vhl = (version << 4) | (headerlen & 0xf);
    

    那么字节会是这样的:

    VVVVHHHH
    

    要取回原始值:

    version = ip_vhl >> 4;
    headerlen = ip_vhl & 0xf;
    

    【讨论】:

      【解决方案4】:
      // Here we are trusting that version and length are both < 0xF
      unsigned char ip_vhl = (unsigned char)version << 4 | (unsigned char)length;
      
      unsigned char version = ip_vhl >> 4;
      unsigned char length = ip_vhl & 0xF;
      

      【讨论】:

        【解决方案5】:

        此外,您还可以使用带有位域的结构:

        typedef struct s_ip_vhl 
        {
            int version : 4;
            int header_length : 4;
        } ip_vhl_type;
        
        ip_vhl_type my_ip_vhl;
        my_ip_vhl.version = 4;
        my_ip_vhl.header_length = 5;
        unsigned char byte = *((byte*)(&my_ip_vhl));
        

        或者您可以将结构与带有 unsigned char 的 union 一起打包,以一次性获取整个字节:

        typedef union u_ip_vhl
        {
            typedef struct s_ip_vhl 
            {
                int version : 4;
                int header_length : 4;
            } ip_vhl_type;
            unsigned char byte;
        } ip_vhl_union;
        

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-05-01
        • 2013-07-10
        • 2017-09-12
        • 2013-03-15
        • 1970-01-01
        • 2015-04-14
        • 2011-03-31
        相关资源
        最近更新 更多