Структура C++, содержащая неподписанную символьную и международную ошибку

Хорошо у меня есть структура в моей программе 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];
};

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

Но если я удаляю "var6" затем, 3 дополнительных байтов не стало.

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

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

5
задан Greg Hewgill 30 May 2010 в 04:21
поделиться

6 ответов

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

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

#pragma pack(1)

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

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

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

6
ответ дан 18 December 2019 в 11:54
поделиться

Ваша структура данных выровнена , так что ваш 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];
};
5
ответ дан 18 December 2019 в 11:54
поделиться

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

4
ответ дан 18 December 2019 в 11:54
поделиться

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

0
ответ дан 18 December 2019 в 11:54
поделиться

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

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

0
ответ дан 18 December 2019 в 11:54
поделиться

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

0
ответ дан 18 December 2019 в 11:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: