Клонировать существующие структуры с различным выравниванием в Visual C ++ - PullRequest
1 голос
/ 05 мая 2010

Есть ли способ клонировать существующую структуру с другим выравниванием элементов в Visual C ++?

Вот фон:

Я использую стороннюю библиотеку, которая определяет несколько структур. Чтобы заполнить структуры, я передаю адрес экземпляров структуры некоторым функциям. К сожалению, функции возвращают только невыровненный буфер, так что данные некоторых членов всегда неверны.

/ Zp не может быть выбран, так как он нарушает другие части программы. Я знаю, #pragma pack изменяет выравнивание следующей определенной структуры, но я бы предпочел не копировать структуры в мой код, поскольку определения в библиотеке могут измениться в будущем.

Пример кода:

library.h:

struct am_aligned
{
  BYTE data1[10];
  ULONG data2;
};

struct untouched
{
  BYTE data1[9];
  int data2;
};

test.cpp:

#include "library.h"

// typedef alignment(1) struct am_aligned am_unaligned;

int APIENTRY wWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
  char buffer[20] = {};

  for (int i = 0; i < sizeof(am_unaligned); i++)
  {
    buffer[i] = i;
  }

  am_aligned instance = *(am_aligned*) buffer;
  untouched useless;

  return 0;
}

am_unaligned - это мое пользовательское объявление, и оно действует только в test.cpp. Закомментированная строка не работает, конечно. нетронутый должен по-прежнему иметь выравнивание по умолчанию.

instance.data2 равен 0x0f0e0d0c, в то время как 0x0d0c0b0a является желательным.

Спасибо за помощь!

Ответы [ 3 ]

0 голосов
/ 05 мая 2010

Не уверен, может быть, __declspec (align ( number )) struct {...} поможет. Подробнее о MSDN

0 голосов
/ 05 мая 2010

Я подозреваю, что единственная проблема, вероятно, связана с начальным адресом буфера в стеке, который не выровнен.

Простое предоставление выровненного буфера вместо не выровненного должно помочь.

Несколько простых способов сделать это:

  • malloc буфер как mallocated адрес в порядке для любого выравнивания.
  • определите ваш буфер как буфер long, он будет выровнен (и скопируйте его, используя memcpy вместо цикла for с приведением к char *, он все равно быстрее)
0 голосов
/ 05 мая 2010

Вы должны использовать #pragma pack перед включением заголовков используемой вами библиотеки (и после, с push и pop). Таким образом, вам не придется определять структуры самостоятельно.

#pragma pack(push, 1)
#include <libraryheader.h>
#pragma pack(pop)

// You can now use the struct defined in the library

Действительно, библиотека была скомпилирована с использованием заданного выравнивания. Вы не можете изменить это , оно уже жестко запрограммировано в двоичной скомпилированной библиотеке. Однако при компиляции файлов вы должны указать компилятору, что структуры, содержащиеся в библиотеке, должны быть определены и использованы с другим выравниванием.

...