2个字节表示C中的3个整数

时间:2010-11-04 11:19:39

标签: c

我有两个字节,8位八位字节,应该读作:[3位] [4位] [3位]。

示例:

unsigned char octet1 = 0b11111111;  // binary values
unsigned char octet2 = 0b00000011;

整数:[7] [15] [7]。

任何人都可以给我一个提示从哪里开始?

10 个答案:

答案 0 :(得分:9)

有一种pseudocode

octet1 = 0b11111111
octet2 = 0b00000011
word = octet1 | octet2<<8
n1 = word & 0b111
n2 = word>>3 & 0b1111
n3 = word>>7 & 0b111

答案 1 :(得分:4)

这是一个使用VC ++ 9

进行测试和编译的方法
#pragma pack( 1 )

union 
{
    struct 
    {
        unsigned short val1:3;
        unsigned short val2:4;
        unsigned short val3:3; 
        unsigned short val4:6; 
    } vals;
    struct 
    {
        unsigned char octet1:8;
        unsigned char octet2:8;
    } octets;
    short oneVal;
} u = {0xFFFF};

unsigned char octet1 = 0xFF;  //1 1111 111
unsigned char octet2 = 0x03;  //000000 11
//000000 111 1111 111 0 7 15 7
u.octets.octet1 = octet1;
u.octets.octet2 = octet2;
cout << "size of u.vals:" << sizeof(u.vals)<< endl;
cout << "size of u.octets:" << sizeof(u.octets)<< endl;
cout << "size of u.oneVal:" << sizeof(u.oneVal)<< endl;
cout << "size of u:" << sizeof(u)<< endl;
cout << endl;

cout << "Your values:" << endl;
cout << "oneVal in Hex: 0x";
cout.fill( '0' );
cout.width( 4 );
cout<< hex << uppercase << u.oneVal << endl;
cout << "val1: " << (int)u.vals.val1 << endl;
cout << "val2: " << (int)u.vals.val2 << endl;
cout << "val3: " << (int)u.vals.val3 << endl;
cout << "val4: " << (int)u.vals.val4 << endl;
cout << endl;

octet1 = 0xCC;  //1 1001 100
octet2 = 0xFA;  //111110 10
//111110 101 1001 100 62 5 9 4
u.octets.octet1 = octet1;
u.octets.octet2 = octet2;

cout << "Some other values:" << endl;
cout << "oneVal in Hex: 0x";
cout.fill( '0' );
cout.width( 4 );
cout<< hex << uppercase << u.oneVal << endl;
cout << dec;
cout << "val1: " << (int)u.vals.val1 << endl;
cout << "val2: " << (int)u.vals.val2 << endl;
cout << "val3: " << (int)u.vals.val3 << endl;
cout << "val4: " << (int)u.vals.val4 << endl;
cout << endl;

octet1 = 0xCC;  //1 1001 100
octet2 = 0xFA;  //111110 10
//111110 101 1001 100 62 5 9 4
u.oneVal = ( (( unsigned short )octet2 ) << 8 ) | ( unsigned short )octet1;
cout << "Some thing diffrent asignment:" << endl;
cout << "oneVal in Hex: 0x";
cout.fill( '0' );
cout.width( 4 );
cout<< hex << uppercase << u.oneVal << endl;
cout << dec;
cout << "val1: " << (int)u.vals.val1 << endl;
cout << "val2: " << (int)u.vals.val2 << endl;
cout << "val3: " << (int)u.vals.val3 << endl;
cout << "val4: " << (int)u.vals.val4 << endl;
cout << endl;

另请注意,我使用 #pragma pack(1)将结构打包设置为1个字节。

我还提供了一种将两个八位字节分配给一个短值的方法。这是否使用按位移位“&lt;&lt;”和按位或“|”

您可以通过删除命名结构来简化对u的访问。但我想展示用于结构的尺寸。

像这样:

union 
{
    struct 
    {
        unsigned short val1:3;
        unsigned short val2:4;
        unsigned short val3:3; 
        unsigned short val4:6; 
    };
    struct 
    {
        unsigned char octet1:8;
        unsigned char octet2:8;
    };
    short oneVal;
} u = {0xFFFF};

访问现在就像

一样简单
u.oneVal = 0xFACC;

u.octet1 = 0xCC;
u.octet2 = 0xFA;

您也可以删除oneVal或octet1和octet2,具体取决于您喜欢的访问方式。

答案 2 :(得分:3)

  oct2|  oct1
000011|1 1111 111
    ---- ---- ---
     7   0xf   7

只是一个提示,(假设它是作业)

答案 3 :(得分:3)

在提取我们想要的位之前,不需要将两个字节放在一起。

#include <stdio.h>

main()
{
    unsigned char octet1 = 0b11111111;
    unsigned char octet2 = 0b00000011;
    unsigned char n1 = octet1 & 0b111;
    unsigned char n2 = (octet1 >> 3) & 0b1111;
    unsigned char n3 = (octet1 >> 7) | (octet2 + octet2);

    printf("octet1=%u octet2=%u n1=%u n2=%u n3=%u\n",
              octet1, octet2, n1, n2, n3);

}

答案 4 :(得分:2)

注意:0x11111111并不意味着8位全部设置为1.它是一个16字节的十六进制数,其中任何字节都设置为0x11。

0xFF是单字节(8位),其中任何位都设置为1。

然后,为了达到你想要的效果,你可以使用一些MACRO来隔离你需要的位:

#define TOKEN1(x)  ((x)>>7)
#define TOKEN2(x)  ( ((x)>>3) & (0xFF>>5) )
#define TOKEN3(x)  ( ((x)>>5) & (0xFF>>5) )

没有测试。

另一个想法,可能是使用位域字符将字符串和结构放入联合

union {
    struct { char a:3; char b:4; char c:3; };
    char x;
};

这样你就可以用x来编辑整个八位字节,用a,b和c来编辑单个标记......

修改:3 + 4 + 3!= 8。

如果你需要10位,你应该使用short而不是char。相反,如果其中一些位重叠,那么使用MACRO的解决方案可能会更容易:你需要在联合内部使用多个结构来实现与第二个解决方案相同的结果......

答案 5 :(得分:1)

您可以使用布尔运算来获取和设置各个值。

目前还不清楚八位字节的哪些位适用于哪些值,但您只需要&(按位AND),|(按位OR),<<(左移)和{{ 1}}(右移)这样做。

答案 6 :(得分:1)

从编写2字节混合的打包/解包功能开始。

如果您使用C / C ++工作 - 您可以使用内在支持:

struct Int3 {
    int a : 3;
    int b : 4;
    int c : 3;
};

答案 7 :(得分:0)

Bitfields可能是一种选择。您可能需要填充结构以使位按照您希望的方式排列。

请参阅Bitfields in C++或搜索StackOverflow以获取C ++和位域,或者您可以在其他答案中使用按位运算符作为大纲。

答案 8 :(得分:0)

你的意思是,如果我们将八位字节“连接”为octet2.octet1,我们将得到000000 [111] [1111] [111]?

然后你可以使用位操作:

  • “&GT;&gt;” 中和“&lt;&lt;”改变你的价值,
  • “&安培;”掩盖比特
  • “+”组合值

例如,可以通过以下方式接收“中间”值(4位长度):

middle = 15 & (octet1 >> 3);

答案 9 :(得分:0)

assert(CHAR_BIT == 8);
unsigned int twooctets = (octet2 << 8) | (octet1); /* thanks, Jonas */
unsigned int bits0to2 = (twooctets & /* 0b0000_0000_0111 */ 0x007) >> 0;
unsigned int bits3to6 = (twooctets & /* 0b0000_0111_1000 */ 0x078) >> 3;
unsigned int bits7to9 = (twooctets & /* 0b0011_1000_0000 */ 0x380) >> 7;