使用联合在位边界上写入

Writing over bit boundaries using unions

本文关键字:边界      更新时间:2023-10-16

我实际上是在尝试使用联合将具有不同位宽的数据块结构转换为一个干净的整数数组。我写了一个小程序来说明我的问题。

#include <stdio.h>
#include <iostream.h>
union {
  struct {
    long blah1;
    short blah2;
    long blah3;
    short blah4;
    int blah5;
  } data;
  int buffer[6];
} db;
int main(int argc, char* argv)
{
  db.data.blah1 = 0x1111111111111111;
  db.data.blah2 = 0x2222;
  db.data.blah3 = 0x3333333333333333;
  db.data.blah4 = 0x4444;
  db.data.blah5 = 0x55555555;
  for(int i=0;i<6;i++) cout << "Word " << i << ": " << std::hex << db.buffer[i] << endl;  
}
输出:

Word 0: 11111111
Word 1: 11111111
Word 2: 2222
Word 3: 0
Word 4: 33333333
Word 5: 33333333
预期输出:

Word 0: 11111111
Word 1: 11111111
Word 2: 33332222
Word 3: 33333333
Word 4: 44443333
Word 5: 55555555

我使用gcc version 4.1.2 20080704 (Red Hat 4.1.2-54)

我有一些格式不正确或我试图使用这个功能的东西,而不是它的目的?有没有另一种方法来实现我的预期输出,而不必使用位操作和无尽的移动?

正如@happydave和Floris指出的那样,可以通过使用pragma pack值为1来停止为位对齐引入的填充来实现结果。

#include <stdio.h>
#include <iostream>
using namespace std;
#pragma pack(push,1)
union {
  struct {
    long blah1;
    short blah2;
    long blah3;
    short blah4;
    int blah5;
  } data;
  int buffer[6];
} db;
#pragma pack(pop)
int main(int argc, char** argv)
{
  db.data.blah1 = 0x1111111111111111;
  db.data.blah2 = 0x2222;
  db.data.blah3 = 0x3333333333333333;
  db.data.blah4 = 0x4444;
  db.data.blah5 = 0x55555555;
  for(int i=0;i<6;i++) cout << "Word " << i << ": " << std::hex << db.buffer[i] << endl;  
}