首页 > 代码库 > 结构体位制详解 -- C

结构体位制详解 -- C

我基本总结下面4部分:

1、占位大小问题。

2、字节对齐问题。

3、特殊保留位0。

4、该结构体在内存中存放位置。


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//基本概念
/*
struct _M
{
	(1)	类型 参数名 : 占位大小;
	(2)	类型 : 占位大小;
}

(1)
	类型 -- int,unsigned(32位),short,char。
	参数名 -- 同个结构体里面不能重名参数。
	占位大小 -- 不能大于类型最最大位数。
	
(2) 一般用于寄存器中保留位
*/

//占位大小问题:
/*
err -- int类型是32位,34大于32位,所以编译出错。
struct _A 
{
	int x1:34;
};

err -- char类型是8位,9大于8位,所以编译出错。
struct _A1 
{
	char x1:9;
};
*/

//字节对齐
/*
	偏移量 -- 类型和占位大小影响(与结构体字节对齐差不多意思)。
*/
struct B 
{
	char x1:1;//1位,字节对齐占1字节,8位。
	char x2:8;
	char x3:1;
	char x4:8;
	char x5:1;
};

struct C 
{
	char x1:4;
	char :1;
	char x2:3;
};

struct _C 
{
	char x1:4;
	char :8;
	char x2:3;
};

//特殊保留位0
struct C1 
{
	char x1:4;
	char :0;//这个0占了4个字节
	char x2:3;
};

struct _C1 
{
	char x1:4;
	char :4;//这个0占了4个字节
	char x2:3;
};



//内存中存放顺序
struct D 
{
	char x1:1;//最低位
	char x2:1;
	char x3:1;
	char x4:1;
	char x5:1;
	char x6:1;
	char x7:1;
	char x8:1;//最高位
};

int
main()
{ 
	//字节对齐
	B b;
	printf("sizeof(b) = %d\n", sizeof(b));
	
	C c;
	printf("sizeof(c) = %d\n", sizeof(c));
	
	_C _c;
	printf("sizeof(_c) = %d\n", sizeof(_c));

	//特殊保留位0
	C1 c1;
	printf("sizeof(c1) = %d\n", sizeof(c1));
	memset(&c1, 0, sizeof(c1) );
	c1.x1 = 0xf;
	c1.x2 = 0x7;
	printf("c1 = 0x%x\n", c1);
	
	_C1 _c1;
	printf("sizeof(_c1) = %d\n", sizeof(_c1));
	memset(&_c1, 0, sizeof(_c1) );
	_c1.x1 = 0xf;
	_c1.x2 = 0x7;
	printf("_c1 = 0x%x\n", _c1);

	//内存中存放顺序
	D d;
	memset(&d, 0, sizeof(d) );
	printf("d = 0x%08x\n", d);
	d.x1 = 1;
	printf("d = 0x%08x\n", d);
	
}

/*
[root@localhost test_class]# gcc quote.cpp ;./a.out
sizeof(b) = 5
sizeof(c) = 1
sizeof(c1) = 2
c1 = 0x70f
sizeof(c2) = 3
d = 0x00000000
d = 0x00000001
[root@localhost test_class]# gcc quote.cpp ;./a.out
sizeof(b) = 5
sizeof(c) = 1
sizeof(_c) = 3
sizeof(c1) = 2
c1 = 0x70f
sizeof(_c1) = 2
_c1 = 0x70f
d = 0x00000700
d = 0x00000701

*/


下面是别人的博客:

在使用结构体位制的时候有两点要特别注意:
1.//位段成员的类型仅能够为unsigned或者int
2.
unsigned b:4;
        unsigned :0;    //定义长度为0的位段时不能指定名字,否则编译不过
        unsigned d:1;   //定义了0字段后,紧接着的下一个成员从下一个存储单元开始存放;                                       //此例子中,d前面那个存储单元中的余下的27位中被0填充了







/*
        DATE : 2010.6.24
        关于C中的位端igned或者int
*/
#include <stdio.h>

typedef struct _A
{
        unsigned int a:4;//位段成员的类型仅能够为unsigned或者int
        unsigned b:4;
        unsigned c:2;
        unsigned d:6;
        unsigned E:1;
        unsigned D:2;
        unsigned T:3;
        unsigned A:9;
        unsigned h:4; //前面已经为31,故4+31>32已超过一个存储单元,所以4在一个新的存储单元存放
        unsigned y:29;//由于前面的4在一个新的存储单元的开头存放,且29+4>32, 故在另一个新的存储单元存放
}A;               //所以最后求出的A的大小是4 + 4 + 4 =12

/*对上面的具体解释: 一个位段必须存储在同一个存储单元中,不能跨两个单元.如果某存储单元空间中不能容纳
              下一个位段,则改空间不用,而从下一个存储单元起存放该位段. 结构体A中的h和y就是这种情况.
                                        在gcc环境下,测试后,一个存储单元为4个字节.
*/

typedef struct _S
{
        unsigned a:4;
        unsigned b:4;
        unsigned c:22;
        unsigned q:1;
        unsigned h:1;
        //unsigned i:33;  // 错误:‘i’ 的宽度超过它自身的类型
        //unsigned i:1;当多出此行时,该结构体大小由4变为8,因为此行之前正好为32位
} S;

typedef struct _T
{       //当没有占满一个存储单元时,结构体的大小对齐为一个存储单元的大小
        unsigned a:2;
        unsigned b:2;
        unsigned j:1;
        unsigned : 1;//可以定义无名位段,此例中该无名位段占用1位的空间,该空间将不被使用
} T;

typedef struct _V
{
        unsigned a:1;
        unsigned b:4;
        unsigned :0;    //定义长度为0的位段时不能指定名字,否则编译不过
        unsigned d:1;   //定义了0字段后,紧接着的下一个成员从下一个存储单元开始存放;
}V;                                     //此例子中,d前面那个存储单元中的余下的27位中被0填充了


int main()
{
        A a; S s; T t; V v;
        printf("sizeof(a)=%d\n", sizeof(a));
        printf("sizeof(s)=%u\nsizeof(t)=%u\n", sizeof(s), sizeof(t));
        printf("sizeof(v)=%d\n", sizeof(v));
        return 0;
}