Я пытаюсь взаимодействовать с кодом Ada с помощью C ++, поэтому я определяю структуру с использованием битовых полей, чтобы все данные на обоих языках находились в одном месте. Следующее - не совсем то, что я делаю, но обрисовывает проблему. Следующее также является консольным приложением в VS2008, но это не очень актуально.
using namespace System;
int main() {
int array1[2] = {0, 0};
int *array2 = new int[2]();
array2[0] = 0;
array2[1] = 0;
#pragma pack(1)
struct testStruct {
// Word 0 (desired)
unsigned a : 8;
unsigned b : 1;
bool c : 1;
unsigned d : 21;
bool e : 1;
// Word 1 (desired)
int f : 32;
// Words 2-3 (desired)
int g[2]; //Cannot assign bit field but takes 64 bits in my compiler
};
testStruct test;
Console::WriteLine("size of char: {0:D}", sizeof(char) * 8);
Console::WriteLine("size of short: {0:D}", sizeof(short) * 8);
Console::WriteLine("size of int: {0:D}", sizeof(int) * 8);
Console::WriteLine("size of unsigned: {0:D}", sizeof(unsigned) * 8);
Console::WriteLine("size of long: {0:D}", sizeof(long) * 8);
Console::WriteLine("size of long long: {0:D}", sizeof(long long) * 8);
Console::WriteLine("size of bool: {0:D}", sizeof(bool) * 8);
Console::WriteLine("size of int[2]: {0:D}", sizeof(array1) * 8);
Console::WriteLine("size of int*: {0:D}", sizeof(array2) * 8);
Console::WriteLine("size of testStruct: {0:D}", sizeof(testStruct) * 8);
Console::WriteLine("size of test: {0:D}", sizeof(test) * 8);
Console::ReadKey(true);
delete[] array2;
return 0;
}
(Если это было непонятно, в реальной программе основная идея состоит в том, что программа получает null*
от чего-то, взаимодействующего с кодом Ada, и переводит его в testStruct*
для доступа к данным, я думаю.)
Если #pragma pack(1)
закомментировано, результат будет следующим:
size of char: 8
size of short: 16
size of int: 32
size of unsigned: 32
size of long: 32
size of long long: 64
size of bool: 8
size of int[2]: 64
size of int*: 32
size of testStruct: 224
size of test: 224
Очевидно, 4 слова (с индексами 0–3) должны быть 4 * 4 * 8 = 32 * 4 = 128 бит, а не 224. Остальные выходные строки должны были помочь подтвердить размер типов в компиляторе VS2008.
Если #pragma pack(1)
раскомментировано, это число (в последних двух строках вывода) уменьшается до 176
, которое по-прежнему больше 128. Похоже, что bools не упаковываются вместе с целыми числами без знака в "Word 0".
Примечание: a & b, c, d, e, f, упакованные в разные слова, будут равны 5, +2 для массива = 7 слов, умноженное на 32 бита = 224
, число, которое мы получаем с закомментированным #pragma pack(1)
. Если c и e (bools) вместо 32 занимают по 8 бит, мы получим 176
, то есть число, которое мы получаем с #pragma pack(1)
без комментариев. Кажется, что #pragma pack(1)
позволяет упаковывать только буллы в отдельные байты вместо слов, но не в буллы с целыми числами без знака вообще.
Итак, мой вопрос в одном предложении: есть ли способ заставить компилятор упаковать через e в одно слово? Связанный с этим вопрос: Упаковка битового поля C ++ с помощью bools, но это не отвечает на мои вопрос; это только указывает на поведение, которое я пытаюсь заставить уйти.
Если буквально нет способа сделать это, есть ли у кого-нибудь идеи обходных путей? Я в растерянности, потому что:
- Меня попросили не изменять формат структуры, который я копирую (без переупорядочивания).
- Я не хочу менять bools на неподписанные целые числа, потому что это может вызвать проблемы в будущем с постоянным повторным преобразованием его в bool и, возможно, случайным использованием неправильной версии перегруженной функции, не говоря уже о том, что код становится более неясным для тех, кто прочтет это позже.
- Я не хочу объявлять их как частные беззнаковые целые числа, а затем делать общедоступные средства доступа или что-то в этом роде, потому что все остальные члены всех других структур в проекте доступны напрямую без
()
впоследствии, поэтому это может показаться немного взломанным и тупым, и можно было бы почти НЕОБХОДИМО использовать IntelliSense или метод проб и ошибок, чтобы запомнить, что нужно()
, а что нет. - Я бы хотел избежать создания другого типа структуры только для преобразования данных (и, например, создания конструктора для
testStruct
, который принимает один объект типаtestStructImport
), потому что фактическая структура очень длинная с большим количеством переменных, указанных в битовых полях.
unsigned
и при необходимости выполнять приведение. - person Mooing Duck   schedule 15.07.2014C
. Кстати, в окнах с g ++ v4.6.2 (MinGW) размер вашей структуры составляет 128 бит, даже без#pragma pack(1)
. - person Holt   schedule 15.07.2014