C ++ структура, содержащая unsigned char и int bug - PullRequest
5 голосов
/ 30 мая 2010

Хорошо, у меня есть структура в моей программе C ++, которая выглядит следующим образом:

struct thestruct
{
 unsigned char var1;
 unsigned char var2;
 unsigned char var3[2];
 unsigned char var4;
 unsigned char var5[8];
 int var6;
 unsigned char var7[4];
};

Когда я использую эту структуру, перед «var6» добавляются 3 случайных байта, если я удаляю «var5», это все еще до «var6», так что я знаю, что всегда перед «var6».

Но если я уберу "var6", то 3 лишних байта исчезнут.

Если я использую только структуру с целым числом int, лишних байтов нет.

Так что, похоже, существует конфликт между неподписанным char и int, как я могу это исправить?

Ответы [ 6 ]

6 голосов
/ 30 мая 2010

Компилятор, вероятно, использует опцию выравнивания по умолчанию, где члены размером x выровнены по границе памяти, равномерно делимой на x .

В зависимости от вашего компилятора вы можете повлиять на это поведение, используя директиву #pragma , например:

#pragma pack(1)

отключит выравнивание по умолчанию в Visual C ++:

Указывает значение в байтах для упаковки. Значение по умолчанию для n равно 8. Допустимые значения: 1, 2, 4, 8 и 16. Выравнивание элемента будет на границе, кратной n * 1019. * или кратный размеру члена, в зависимости от того, что меньше.

Обратите внимание, что по причинам низкой производительности ЦП обычно лучше попытаться выровнять элементы данных так, чтобы они попадали на выровненную границу. Некоторые архитектуры ЦП требуют выравнивания, в то время как другие (например, Intel x86) допускают смещение с уменьшением производительности (иногда весьма значительно).

5 голосов
/ 30 мая 2010

Ваша структура данных выровнена на , так что ваш int попадает в границы слов, которые для вашей цели могут быть 32 или 64 бита.
Вы можете реорганизовать свою структуру так, чтобы этого не произошло:

struct thestruct
{
 int var6;
 unsigned char var1;
 unsigned char var2;
 unsigned char var3[2];
 unsigned char var4;
 unsigned char var5[8];
 unsigned char var7[4];
};
4 голосов
/ 30 мая 2010

Вы говорите о дополнительных байтах? Это не ошибка. Как разрешено стандартом C ++, компилятор добавляет отступы, чтобы члены выровнялись . Это требуется для некоторых архитектур и значительно улучшит производительность для других.

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

Несмотря на то, что изменение порядка, в котором вы объявляете элементы данных внутри struct, является нормальным, следует подчеркнуть, что переопределение выравнивания по умолчанию с использованием #pragma s и такое плохая идея , если вы не знаете точно что ты делаешь. В зависимости от вашего компилятора и архитектуры, попытка получить доступ к невыровненным данным, в частности, путем сохранения адреса в указателе и последующей попытки разыменования, может легко привести к ужасной ошибке шины или другому неопределенному поведению.

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

Считайте выравнивание структуры данных . По сути, в зависимости от параметров компилятора и компиляции вы получите выравнивание по различным степеням 2.

Чтобы избежать этого, перемещайте многобайтовые элементы ( int или указатели) перед однобайтовыми (со знаком или без знака char ) элементами - хотя они все еще могут быть там после вашего последнего предмета.

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

У вас проблема с выравниванием байтов. Компилятор добавляет отступы для выравнивания байтов. См. эту статью в Википедии.

...