Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/4: Рейтинг темы: голосов - 4, средняя оценка - 5.00
12 / 3 / 0
Регистрация: 12.07.2015
Сообщений: 69
1

Что с размером структуры?

25.08.2018, 01:30. Показов 719. Ответов 10
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Есть структура, которая по моим несложным расчётам, должна занимать 14 байт:
C++
1
2
3
4
5
6
7
8
struct bmpheader {
    char Type[2];//2
    int size;//4
    short Reserved1;//2
    short Reserved2;//2
    int offsetbit;//4
};
bmpheader testheader;
Вопрос: почему 16 байт?
Немного наговнокодив, я выяснил, что после char Type[2]; вставляются ещё 2 лишних нулевых байта... Почему?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    testheader.Type[0] = 'B';
    testheader.Type[1] = 'M';
    testheader.size = 7777123;
    testheader.Reserved1 = 1234;
    testheader.Reserved2 = 6451;
    testheader.offsetbit = 87576;
    hexprint((char*) &testheader, sizeof(testheader));
    std::cout << '\n';
    headerhexprinth(&testheader);
 
//...
 
void hexprint(char* data, short size) {
    for(short i = 0; i < size; i++) {
        std::cout << i << ": " << (short) data[i] << ":\t" << data[i] << std::endl;
    }
}
 
void headerhexprinth(bmpheader* header) {
    std::cout << "0: " << (short) *(((char*) header) + 0) << " " << (short) *(((char*) header) + 1) << ":\t" << *(((char*) header) + 0) << *(((char*) header) + 1) << '\n';
    std::cout << "2: " << *((short*) (((char*) header) + 2)) << "\t\t<< Вот тут лишние 2 байта!" << '\n';
    std::cout << "4: " << *((int*) (((char*) header) + 4)) << '\n';
    std::cout << "8: " << *((short*) (((char*) header) + 8)) << '\n';
    std::cout << "10: " << *((short*) (((char*) header) + 10)) << '\n';
    std::cout << "12: " << *((int*) (((char*) header) + 12)) << '\n';
}
Вывод
16
0: 66: B
1: 77: M
2: 0:
3: 0:
4: 99: c
5: -85: «
6: 118: v
7: 0:
8: -46: Т
9: 4: ╝
10: 51: 3
11: 25:
12: 24:
13: 86: V
14: 1: ╔
15: 0:

0: 66 77: BM
2: 0 << Вот тут лишние 2 байта!
4: 7777123
8: 1234
10: 6451
12: 87576
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
25.08.2018, 01:30
Ответы с готовыми решениями:

Из массива Х размером nx, сформировать массив Y размером ny, что бы элементы из массива X не повторялись в Y
Вот что получилось, но почему-то не удаляет повторяющиеся элементы mov esi,0 mov ecx,nx...

Динамические структуры данных, списковые структуры (надо разобраться что делает программа)
дана программа, надо помочь выяснить что в ней делает каждая подпрограмма unit Unit6; ...

Исследование структуры FILE или: что вообще можно выудить из этой структуры, указатель на которую мы получаем при открытии файла?
Ничего нельзя. Итак, новичкам напомню, что после выполнения кода FILE* f= fopen (&quot;file.txt&quot;,...

Оптимизация кода, структуры базы, или что еще можно сделать что бы быстрее работало!?
Всем привет! Господа, выручайте. Не пойму как еще оптимизировать... Есть куча связанных таблиц....

10
4064 / 3318 / 924
Регистрация: 25.03.2012
Сообщений: 12,495
Записей в блоге: 1
25.08.2018, 01:31 2
https://habr.com/post/142662/
1
Заблокирован
25.08.2018, 05:12 3
Компилятор-то какой? В зависимости от настроек char может быть 2 байта. Ну и про выравнивание полей, конечно, не надо забывать.
0
4064 / 3318 / 924
Регистрация: 25.03.2012
Сообщений: 12,495
Записей в блоге: 1
25.08.2018, 05:24 4
Verevkin, там поля выровнены это 100%. char не может занимать 2 байта
1
2376 / 834 / 317
Регистрация: 10.02.2018
Сообщений: 1,968
25.08.2018, 09:37 5
Скорее всего, дело именно в выравнивании.
Если посмотреть на данную структуру в заголовках виндовс, то можно увидеть примерно такое:
C++
1
2
3
4
5
6
7
8
9
10
11
#include <pshpack2.h>
 
typedef struct tagBITMAPFILEHEADER {
        WORD    bfType;
        DWORD   bfSize;
        WORD    bfReserved1;
        WORD    bfReserved2;
        DWORD   bfOffBits;
} BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;
 
#include <poppack.h>
Структура обрамлена двумя специфичными инклудами, именно они обеспечивают правильную упаковку и выравнивание полей в структуре, независимо от общих настроек проекта. Как я понимаю, эти инклуды специфичны для microsoft и не являются частью стандарта C++ (align (C++)). Так что в иных компиляторах должны быть свои инструменты для подобного.
1
3881 / 2479 / 418
Регистрация: 09.09.2017
Сообщений: 10,888
25.08.2018, 10:21 6
C
1
2
3
struct __attribute__((__packed__))S{
...
};
Так работает в gcc
C
1
2
3
4
5
6
#pragma pack(push)
#pragma pack(1)  
struct __attribute__((__packed__))S{
...
};
#pragma pack(pop)
а так в mingw
Что-то мне подсказывает, что содержимое pshpack2.h выглядит как-то так
C
1
2
3
#pragma pack(push)
#pragma pack(2)
__attribute__((__packed__))
А содержимое poppack.h как-то так
C
1
#pragma pack(pop)
Ну может с добавлением чего-то ms-специфичного
1
2376 / 834 / 317
Регистрация: 10.02.2018
Сообщений: 1,968
25.08.2018, 11:25 7
pshpack2.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
#if ! (defined(lint) || defined(RC_INVOKED))
#if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED)
#pragma warning(disable:4103)
#if !(defined( MIDL_PASS )) || defined( __midl )
#pragma pack(push,2)
#else
#pragma pack(2)
#endif
#else
#pragma pack(2)
#endif
#endif /* ! (defined(lint) || defined(RC_INVOKED)) */

poppack.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
#if ! (defined(lint) || defined(RC_INVOKED))
#if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED)
#pragma warning(disable:4103)
#if !(defined( MIDL_PASS )) || defined( __midl )
#pragma pack(pop)
#else
#pragma pack()
#endif
#else
#pragma pack()
#endif
#endif /* ! (defined(lint) || defined(RC_INVOKED)) */

Как я понимаю, у microsoft структуры выравниваются в зависимости от опции компилятору "/Zp". По умолчанию для 32х битных приложений 4, для 64х битных 8. Эта опция задаётся и переопределяется настройками проекта --> настройками файла --> pragma pack. Данное выравнивание применяется дефолтно при отсутствии в объявлениях структур явно указанных модификаторов __declspec(align(...)). Если модификаторы присутствуют, то они приоритетней. Ну и формат pragma pack менялся со временем, сперва в синтаксисе не было предусмотрено push и pop, были только установка нового и возврат к дефолтному.
1
Заблокирован
25.08.2018, 12:03 8
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
char не может занимать 2 байта
Чо, правда?
Ну ладно, я тогда пошёл пиво пить.
0
12 / 3 / 0
Регистрация: 12.07.2015
Сообщений: 69
25.08.2018, 12:26  [ТС] 9
В общем, дело действительно оказалось в выравнивании, и вот так всё заработало как надо:
C++
1
2
3
4
5
6
7
8
9
#pragma pack(push, 1)
struct bmpheader {
    char Type[2];//2
    int size;//4
    short Reserved1;//2
    short Reserved2;//2
    int offsetbit;//4
};
#pragma pack(pop)
Правда, я, после неудачной попытки залинковаться с dll уже приучил считать себя все эти pragma опциями, характерными для определённых компиляторов, и мне как-то не очень хочется использовать для такой достаточно частой опции что-то, что может где-то не работать... (Если что, я использую g++.exe в mingw-w64) Ну да ладно... Короче,
Kuzia domovenok, спасибо за статью... А то если бы сам начал разбираться, то, скорее всего, тупо бы подумал, что выравнивание происходит просто по границе в 4 байта, сомневаюсь, что я бы это с типом самого поля связал... Да и к тому-же, там я про битовые поля узнал. Крутая штука, оказывается...
Ygg, о, так bitmapheader где-то в стандартных заголовках есть... Но я всё равно лучше свою структуру использовать буду, а то ещё искать, где он там...
COKPOWEHEU, , так, тут что-то посложнее пошло... вместо push и 1 в одних скобках они тут отдельными pgarma'ми, да ещё и __attribute__((__packed__))S какой-то... Ну да ладно, пойду, тогда, по подробнее про эти pragma pack где-нибудь почитаю...
0
3881 / 2479 / 418
Регистрация: 09.09.2017
Сообщений: 10,888
25.08.2018, 15:52 10
Цитата Сообщение от Max_Cross Посмотреть сообщение
вместо push и 1 в одних скобках они тут отдельными pgarma'ми
Их можно объединить, но можно писать и по отдельности.
Цитата Сообщение от Max_Cross Посмотреть сообщение
да ещё и __attribute__((__packed__))
А вот это, в отличие от прагмы, указание компилятору. Теоретически, одного этого атрибута должно быть достаточно для максимальной упаковки. Но разработчики компиляторов считают иначе.
Цитата Сообщение от Max_Cross Посмотреть сообщение
Правда, я, после неудачной попытки залинковаться с dll уже приучил считать себя все эти pragma опциями, характерными для определённых компиляторов, и мне как-то не очень хочется использовать для такой достаточно частой опции что-то, что может где-то не работать...
Это правильный подход. Хорошо бы где-то в коде вкрутить специальную проверку поддерживается ли такая прагма. Впрочем, компиляторы должны и сами говорить "я такой прагмы не знаю".
1
Эксперт С++
1624 / 954 / 782
Регистрация: 06.02.2016
Сообщений: 2,452
Записей в блоге: 31
26.08.2018, 12:14 11
https://tproger.ru/translation... e-packing/ Очень неплохо написано про выравнивание, с примерами
0
26.08.2018, 12:14
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
26.08.2018, 12:14
Помогаю со студенческими работами здесь

Можно ли коробку размером a b c упаковать в посылку размером r s t? «Углом» укладывать нельзя
Можно ли коробку размером abc упаковать в посылку размером rst? «Углом» укладывать нельзя.

Из заданного одномерного массива A размером N получить квадратную матрицу B размером M х M
Помогите Из заданного одномерного массива A размером N получить квадрат- ную матрицу B размером M...

Просуммировать элементы матрицы строк размером 4*3. Результат получить в одномерном массиве размером 4
Помогите люди добрые! Завтра сдавать, а я маягко говоря не шарю, прошу профессионалов выручить...

Из заданной матрицы A размером N*M получить матрицу В размером K*3 по правилу: первый столбец состоит из полож
Из заданной матрицы A размером N*M получить матрицу В размером K*3 по правилу: первый столбец...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru