在编程中遇到处理位的运算时,一般用结构体定义位长度;比如在发送邮件程序中,数据必须由24位(3个字节)转化为4个字节(每个字节6位),这样才能被邮件服务器识别。
需要注意的是:
(1)数据在计算机中存储方式,比如:
数值: 0x99
存储:1001 1001
但是位段在内存中的存储是从右向左,看下面例程:
#include <stdio.h>
#include <stdlib.h>
union share
{
char val;
struct STR1
{
unsigned a : 3;
unsigned b : 2;
unsigned c : 3;
}str1;
struct STR2
{
unsigned b1 : 5;
unsigned b2 : 2;
}str2;
};
//0x99
// 1001 1001
int main(void)
{
union share m_struct;
m_struct.val = 0x99; // 1001 1001
printf("sec1: %d\n", m_struct.str1.a); //001
printf("sec2: %d\n", m_struct.str1.b); //11
printf("sec3: %d\n", m_struct.str1.c); //100
printf("b1: %d\n", m_struct.str2.b1); //11001
printf("b2: %d\n", m_struct.str2.b2); /00
}
程序运行结果:
sec1: 1
sec2: 3
sec3: 4
b1: 25
b2: 0
邮件发送代码的转换如下:
typedef struct Base64Cov
{
unsigned int sect1 : 6;
unsigned int sect2 : 6;
unsigned int sect3 : 6;
unsigned int sect4 : 6;
}BASE64COV_S;
int main(void)
{
int a = 0x030201; //10;
BASE64COV_S* pst;
pst = (BASE64COV_S*)&a;
// 0000 0011 0000 0010 0000 0001
printf("%d\n", pst -> sect1);
printf("%d\n", pst -> sect2);
printf("%d\n", pst -> sect3);
printf("%d\n", pst -> sect4);
}
结果:
1
8
48
0
(2) 《C和指针》指出:
注重可移植性的程序应该避免使用位段 。由于下面这些与实现有关的依赖性、位段在不同的系统中可能有不同的结果。
1、int位段被 当作有符号数还是无符号数。
2、位段中位的最大数目。许多编译器把位段成员的长度限制在一个整形值的 长度之内,所以一个能够运行于32位整数的机器上的位段声明可能在16位整数的机器上无法运行。(注:现在也有64位机器)
3、位段中的成员在内存中是从左向右分配的还是从右 向左分配的。
4、当一个声明指定了两个位段,第2个位段比较大,无法容纳于第1个位段剩余的位时 ,编译器有可能把第2个位段放在内存的下一个字 ,也可能直接放在第1个位段后面,从而在两个内存位置的边界上形成重叠。
由上面的论述可见,位段在内存中的表示没有统一的标准,各家编译器厂商实现的方式可能不一样。 注意内存大小端表示的不同