C 语言中位操作技巧

作者: comcat 发表日期: 2006-10-17 21:04     http://comcat.blog.openrays.org/blog.php?do=showone&tid=130

 

注: 本文仅讨论常见的小端机器

1. 声明

对于RGB模式下, 8 bit 颜色可以用一个字节描述:

7 5 4 2 1 0
|-------|--------|-----|
R G B
|---------------------|


则可以定义数据结构为:

struct color8
{
unsigned char blue : 2; // 2 bit for B
unsigned char green : 3; // 3 bit for G
unsigned char red : 3; // 3 bit for R
};

容易得到 sizeof(struct color8) 的值为 1 Byte


注意 struct color8 中成员的声明顺序, 先声明的成员,在内存中的位置在低位

使用上面的 struct color8, 可以很容易的转为1字节,用于显示:

struct color8 c8;

c8.red = 4; // 值不能超过7
c8.green = 0;
c8.blue = 2;
unsigned char * tran = (unsigned char *)&c8

printf("8 bit color value is: 0x%x\n", *tran);

//100 000 10
则输出为: 8 bit color value is: 0x82


2. 赋值

低位赋予原则,直至目的变量之所有位填满.

如:

struct color8 c8;
unsigned char i = 0x82; // 1000 0010

c8.blue = i; // 将 i 之低2位(1~0)赋给成员blue(长2位), 其值为 0x2
c8.green = i >> 2; // 将 i 之 4~2 位赋予成员green(长3位), 其值为 0x0
c8.red = i >> 5; // 将 i 之 7~5 位赋给成员red(长3位), 其值为 0x4


3. 16bit 值的合并

在RGB模式下, 16 bit 颜色可以用二个字节描述:

15 14 10 9 5 4 0
|---|-------|-------|-------|
| x | R | G | B |
|--------------------------|

struct color16
{
unsigned char b:5;
unsigned char g:5;
unsigned char r:5;
unsigned char ge:1;
};

注意到 sizeof(struct color16) 的值为 3 Byte

因为要便于机器访问以字节为单位的存储单元,上述结构在内存中的布局为:

7 5 4 0
|------|---------| 低地址
| 0 | b |
|------|---------|
| 0 | g |
|------|---------|
| 0 |ge| r |
|------|---------| 高地址

故而:

struct color16 cx;
cx.r = 4;
cx.g = 1;
cx.b = 3;
cx.ge = 1;
printf(" 0x%x \n", *((unsigned short*)&cx));

输出为 0x103,

分析:

经赋值后内存映象为:

000 00011 -----> 1st byte
000 00001 -----> 2nd byte
001 00100 -----> 3rd byte

强制地址转换后访问前二个字节,输出时则为: 0000 0001 0000 0011


又:
printf(" 0x%x \n", *((unsigned char*)&cx + 2));

输出为 0x24, 即为第三个字节 0010 0100 的值


经以上分析,在非对齐的数据结构中使用指针强制转换的方式合并数据位是不可行的,
可用以下方法实现:

unsigned short tt = 0, t = 0;
t = cx.ge;
t <<= 15;
tt = t;

t = cx.r;
t <<= 10;
tt |= t;

t = cx.g;
t <<= 5;
tt |= t;

tt |= cx.b;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值