将无符号整数存储到结构中

时间:2009-05-19 13:55:27

标签: c

我已经编写了这段代码,我已经为两个不同的结构分配了一个无符号整数。实际上它们是相同的,但其中一个具有__attribute __((packed))。


  #include 
  #include 

  struct st1{
    unsigned char opcode[3];
    unsigned int target;
  }__attribute__((packed));

  struct st2{
    unsigned char opcode[3];
    unsigned int target;
  };


  void proc(void* addr) {
    struct st1* varst1 = (struct st1*)addr;
    struct st2* varst2 = (struct st2*)addr;
    printf("opcode in varst1: %c,%c, %c\n",varst1->opcode[0],varst1->opcode[1],varst1->opcode[2]);
    printf("opcode in varst2: %c,%c,%c\n",varst2->opcode[0],varst2->opcode[1],varst2->opcode[2]);
    printf("target in varst1: %d\n",varst1->target);
    printf("target in varst2: %d\n",varst2->target);

  };

  int main(int argc,char* argv[]) {
    unsigned int* var;
    var =(unsigned int*) malloc(sizeof(unsigned int));
    *var = 0x11334433;

    proc((void*)var);

    return 0;
  }

输出结果为:

opcode in varst1: 3,D,3
opcode in varst2: 3,D,3
target in varst1: 17
target in varst2: 0

鉴于我正在存储这个号码 0x11334433 == 00010001001100110100010000110011

我想知道为什么这是我得到的输出。

3 个答案:

答案 0 :(得分:3)

这与数据对齐有关。大多数编译器会将地址边界上的数据对齐,以帮助实现一般性能。因此,在第一种情况下,具有packed属性的struct,char [3]和int之间有一个额外的字节,用于在四字节边界上对齐int。在打包版本中,填充字节丢失。

byte  :      0       1         2         3      4   5   6   7
st1   : opcode[0] opcode[1] opcode[2] padding |----int------|
st2   : opcode[0] opcode[1] opcode[2] |-------int--------|

您分配一个unsigned int并将其传递给函数:

byte  :      0       1         2         3      4   5   6   7
alloc :   |-----------int------------------| |---unallocated---|
st1   : opcode[0] opcode[1] opcode[2] padding |----int------|
st2   : opcode[0] opcode[1] opcode[2] |-------int--------|

如果你使用的是小端系统,那么最低的8位(最右边)存储在字节0(0x33),字节1有0x44,字节2有0x33,字节4有0x11。在st1结构中,int值映射到超出分配量末尾的内存,而st2版本int的最低字节映射到字节4,0x11。因此st1产生0,st2产生0x11。

很幸运,未分配的内存为零,并且您没有进行内存范围检查。在这种情况下写入st1和st2中的int可能会在最坏的情况下破坏内存,生成内存保护错误或什么都不做。它是未定义的,取决于内存管理器的运行时实现。

一般情况下,请避免使用void *

答案 1 :(得分:1)

您的字节如下所示:

00010001 00110011 01000100 00110011

虽然显然你的字节顺序是错误的,事实上它们是这样的:

00110011 01000100 00110011 00010001

如果您的结构被打包,那么前三个字节与操作码相关联,第四个字节是目标 - 这就是为什么压缩数组的目标数为17 - 0001001(二进制)。

解压缩的数组用零填充,这就是为什么varst2中的目标为零的原因。

答案 2 :(得分:0)

  • %c将参数解释为字符的ascii代码并打印字符
  • 3的ascii代码是0x33
  • D的ascii代码是0x44
  • 17是0x11

int根据处理器体系结构存储小端或大端 - 您不能依赖它按顺序进入struct的字段。

解压缩版本中的int目标超过了int的位置,因此它保持为0。