【问题标题】:unpredictable answer in bitfield [duplicate]位域中不可预测的答案[重复]
【发布时间】:2013-04-12 17:07:42
【问题描述】:

请您解释一下为什么这段代码的输出是 12 (1100b)

以及sizeof(bit1)是怎么变成4byte的???

#include <stdio.h>
#include <stdlib.h>
struct bitfield
  {
   unsigned a:5;
   unsigned c:5;
   unsigned b:6;

  };

void main()
{

 char *p;
 struct bitfield bit1={1,3,3};  //a=00001 ,c=00011 ,b=000011
 p=&bit1;                           // p get the address of bit1
 p++;                               // incriment the address of p in 1

 printf("%d\n",*p); 

 printf("%d\n",sizeof(bit1));            
}

【问题讨论】:

  • 您可能想查看有关成员地址、位域成员以及位域如何“特殊”的标准。我也很好奇你是如何没有struct bitfield * 类型直接分配到 char * 收到 phat 警告的。
  • sizeof(bit1) 不是 2byte(16bit) 输出应该是 195(11000011b)???
  • @Anklon 编译器通常会为structs 添加填充以用于对齐目的(以便您可以创建它们的数组)。你的编译器可能有类似#pragma pack 的选项来控制它。 c-faq.com/struct/endpad.html
  • C99 6.7.2.1p11 实现可以分配任何大到足以容纳位字段的可寻址存储单元。如果有足够的空间,结构中紧跟在另一个位域之后的位域将被打包到同一单元的相邻位中。如果剩余空间不足,则将不适合的位域放入下一个单元还是与相邻单元重叠是实现定义的。单元内位域的分配顺序(高位到低位或低位到高位)是实现定义的。未指定可寻址存储单元的对齐方式。
  • 我建议使用%zu 打印size_t 类型的值(例如sizeof 表达式的结果)。

标签: c


【解决方案1】:

您已将位字段声明为unsigned。在大多数现代系统上,这是一个 32 位整数。 (unsigned short 是 16、char 8、long 64 等)所以,您声明的是 32 位位域容器。每个单独的位域参数的大小由位域名称后面的整数给出,但它们所在容器的大小是指定数据类型的倍数……通常是指示的总位数的最小倍数适合——尽管单词边界和其他东西会影响到这一点。

我很惊讶它的其余部分都能正常工作。除了指针中的转换问题之外,printf 正在打印整个字段的前 8 位......一个单个字符。这不会在位字段本身上中断,而是在字节/字符内存边界上中断。根据您的系统是大端还是小端,它将是整个字段的 MSB 或 LSB。

【讨论】:

  • 嗯,没有。位域的大小由其后的数字决定;位宽分别为 5、5 和 6。
  • individual 位域的大小,是的。但是它们包装的容器的大小是由类型定义的。它将是该类型的倍数。
  • 当我提到它是有符号的或没有提到它是有符号或无符号时...两种情况都显示 sizeof(bit1) 是 4 字节...
  • 如果你声明是unsigned short?
  • 您说“它将是类型的倍数”.. 那么它应该是 4*3=12 字节,因为 unsigned int 也是 4 字节(对于我的编译器)
【解决方案2】:

指针p包含结构变量bit1的地址。

我相信你的系统有 little endian 寻址,因此变量 b 被放置在指针 p 指向的位置,*p 打印 @987654324 的前两个字节的内容@。

在你的情况下b=3 (000011)

但是这两个字节包含,

00000000 00001100  (12)
         ------
            ^
            |
         Value of b

为了更好地理解这一点,

如下将b的值改为5(000101),

struct bitfield bit1={1,1,5}; 

那么你的输出将是 20,因为,

00000000 00010100  (20)
         ------
           ^
           |
        Value of b

结构bitfieldacb 打包成一个无符号整数。无符号整数的大小为 4 字节

【讨论】:

    猜你喜欢
    • 2018-03-07
    • 2012-03-28
    • 2022-11-19
    • 1970-01-01
    • 2012-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多