#include<stdio.h>
static struct s
{
unsigned a:5;
unsigned b:5;
unsigned c:5;
unsigned d:5;
}v={1,2,3,4};
int main()
{
printf("size of v = %d\n",sizeof(v));
}
“答案是4”。我无法解释这个输出。
#include<stdio.h>
static struct s
{
unsigned a:5;
unsigned b:5;
}v={1,2};
int main()
{
printf("size of v = %d\n",sizeof(v));
}
“答案还是4” ..比特字段如何影响结构大小?
答案 0 :(得分:4)
默认情况下,gcc在字节边界上对齐数据,在机器字边界的某些平台(尤其是RISC)上对齐数据。这是因为非字节对齐的读取(在RISC机器上)会导致异常,从而减慢程序的速度。
这就是为什么每个字段都存储在它们自己的字节中,即使它们只有5位长。为了正确包装,请使用__attribute__((packed))
:
#include<stdio.h>
static struct s
{
unsigned a:5 __attribute__((packed));
unsigned b:5 __attribute__((packed));
}v={1,2};
int main()
{
printf("size of v = %d\n",sizeof(v));
}
这个输出是:
size of v = 2
这是预期的,因为你总共有10个字节,大小被四舍五入到下一个字节。
答案 1 :(得分:2)
如果您使用unsigned char
作为位字段的类型,那么您将获得4和2的大小。 struct
的对齐和大小通常由位域的整数类型确定。结构的封装,特别是位域的封装,是高度实现的,但由6.7.2.1 ad 11规定
实现可以分配足够大的任何可寻址存储单元来保存位字段。如果剩余足够的空间,则紧跟在结构中的另一个位字段之后的位字段将被打包到相同单元的相邻位中。如果剩余的空间不足,则是否将不适合的位域放入下一个单元或重叠相邻单元是实现定义的。单元内的位域分配顺序(高阶到低阶或低阶到高阶)是实现定义的。可寻址存储单元的对齐未指定。
大多数编译器使用位字段给出的整数类型作为“可寻址存储单元”。
另请注意,结构打包通常被指定为体系结构的应用程序二进制接口(ABI)的一部分,以确保此体系结构的编译器的互操作性。
在假设G86架构的GCC编译器的基础上,详细阐述您的示例。
struct
{ unsigned int a:5;
unsigned int b:5;
unsigned int c:5;
unsigned int d:5;
};
这四个位字段位于32位容器的前20位。
struct
{ unsigned char a:5;
unsigned char b:5;
unsigned char c:5;
unsigned char d:5;
};
每个位字段位于其自己的8位容器中,因此也是32位。
struct
{ unsigned int a:5;
unsigned int b:5;
};
位字段位于32位容器的前10位,因此整个结构仍为32位。
struct
{ unsigned char a:5;
unsigned char b:5;
};
两个位域都位于各自的8位容器中,因此整个结构为16位。
struct
{ unsigned char a:5;
unsigned char b:3;
unsigned char c:3;
unsigned char d:5;
unsigned char e:5;
};
位字段a
和b
位于8位容器中。位字段c
和d
位于8位容器中,位字段e
位于8位容器中,总共为24位。
答案 2 :(得分:1)
很简单,因为处理器喜欢4(AKA data alignment)
答案 3 :(得分:0)
C编译器使用单个unsigned int作为位字段的存储。因为unsigned int的长度为4个字节,所以结构大小也不可避免地为4个字节。