Сохранение целого числа без знака в структуры

голоса
2

Я написал этот кусок кода, где я назначенный беззнаковое целое с двумя различными структурами. На самом деле они одинаковы, но один из них имеет __attribute __ ((упакована)).


  #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

Я хотел бы знать, почему это выход я получаю.

Задан 19/05/2009 в 14:55
источник пользователем
На других языках...                            


3 ответов

голоса
0
  • % C интерпретирует аргумент как ASCII код символа и выводит символ
  • 3 По ASCII-код 0x33
  • Двойки ASCII код 0x44
  • 17 0x11

ИНТ хранится Little Endian или большой Endian в зависимости от архитектуры процессора - вы не можете зависеть от него происходит в полях вашей структуры в порядке.

Мишень INT в распакованной версии мимо позиции междунар, так что остается 0.

Ответил 19/05/2009 в 15:00
источник пользователем

голоса
1

Ваши байты выглядеть следующим образом:

00010001 00110011 01000100 00110011

Хотя, очевидно, ваш порядок байт не так, и на самом деле они, как это:

00110011 01000100 00110011 00010001

Если ваша структура упакована, то первые три байта связаны с опкодом, а четвёртый является целью - вот почему упакованный массив имеет atarget 17 - 0001001 в двоичной системе.

Распакованы массив дополняется нулями, поэтому цель в varst2 равна нулю.

Ответил 19/05/2009 в 15:01
источник пользователем

голоса
3

Это связано с выравниванием данных. Большинство компиляторов выравнивать данные по границам адресов, которые помогают с общей производительностью. Так, в первом случае структура с упакованным атрибутом, есть дополнительные байты между угла [3] и междунаром для выравнивания 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--------|

Вы выделяете неподписанных 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--------|

Если вы используете маленькую систему Endian, то самые низкие восемь бит (самый правый) хранятся в байте 0 (0x33), байт 1 имеет 0x44, байт 2 имеет 0x33 и байт 4 имеет 0x11. В структуре st1 значение INT преобразуется в памяти за пределы конца выделенной суммы и версии st2 самый низкий байт Int отображаетс в байте 4, 0x11. Так st1 производит 0 и st2 производит 0x11.

Вам повезло, что нераспределенные памяти равен нулю, и что у вас нет проверки диапазона памяти не происходит. Запись в Интс в st1 и st2 в этом случае может произойти повреждение памяти в худшем случае, приводит к возникновению ошибок сторожевых памятей или ничего не делать. Он не определен и зависит от реализации во время выполнения диспетчера памяти.

В общем, избежать void *.

Ответил 19/05/2009 в 15:07
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more