Размер структуры
Выводит размер структуры как 20. Почему 20? Почему не 17.
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:

Размер структуры
Помогите узнать размер структуры: enum UnitType < Swordsman, // мечник Archer, //.
Размер структуры?
Здравствуйте, дорогие форумчане! Есть доп. зд — подсчитать размер структуры. Только я очень слабо.
Странный размер структуры
Привет. Есть структура typedef struct t_ANDNonDirectionalBeacon < unsigned long track_id; .
Размер структуры KEYBOARD_ATTRIBUTES
Пытаюсь портировать с c++ структуру KEYBOARD_ATTRIBUTES (.
4816 / 2276 / 287
Регистрация: 01.03.2013
Сообщений: 5,943
Записей в блоге: 27
Мобыть выравнивание лесов/полей?
Котовчанин
942 / 482 / 200
Регистрация: 16.02.2010
Сообщений: 3,338
Записей в блоге: 37
Сообщение от _Ivana 
Мобыть выравнивание лесов/полей?
Так а как оно происходит?
4816 / 2276 / 287
Регистрация: 01.03.2013
Сообщений: 5,943
Записей в блоге: 27
Я не спец, но думаю, как компилятор на память положит. Может есть какие прагмы чтобы влиять на его поведение в этих случаях. Можно погуглить, начав с «выравнивание полей структур».
Может у вас 32-разрядная система и компилятор под чары в структурах выделяет размер регистра — 4 байта.
![]()
13663 / 10580 / 6322
Регистрация: 18.12.2011
Сообщений: 28,248
Выравнивание идет на границы 32 битного слова.
Поэтому после каждого из char останется по 3 байта.
Итого: (1+3)+3*4+(1+3)=20 байт.
Котовчанин
942 / 482 / 200
Регистрация: 16.02.2010
Сообщений: 3,338
Записей в блоге: 37
zss, то есть, любой тип приводится к 4-м?
Все, что меньше 4-х:
char x[3];
short x;
4816 / 2276 / 287
Регистрация: 01.03.2013
Сообщений: 5,943
Записей в блоге: 27
Имхо к длине машинного слова данной архитектуры. В вашем случае это 4 байта.
Котовчанин
942 / 482 / 200
Регистрация: 16.02.2010
Сообщений: 3,338
Записей в блоге: 37
_Ivana, zss, дошло, спасибо!
4816 / 2276 / 287
Регистрация: 01.03.2013
Сообщений: 5,943
Записей в блоге: 27
Тамика, раз пошла такая пьянка — попробуйте запилить структуру с 4 чарами подряд и двумя интами и посмотрите ее размер. А потом погуглите какую-нибудь packed — прагму или что там бывает, чтобы добиться ужатия первых четырех чаров в одно 32-битное слово.
Котовчанин
942 / 482 / 200
Регистрация: 16.02.2010
Сообщений: 3,338
Записей в блоге: 37
Практика подтвердила!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
struct T { short int i; int a = 66; int b = 77; int c = 88; char j; }; void show(const char* aT, size_t size) { for (int i = 0; i size; ++i) std::cout <"i " <static_castint>(aT[i]) <"\n"; } int main() { T t; show(static_castchar*>(static_castvoid*>(&t)), sizeof(t)); system("pause>nul"); }
Добавлено через 33 секунды
Сообщение от _Ivana 
packed — прагму
Простите, но. Энто што.
4816 / 2276 / 287
Регистрация: 01.03.2013
Сообщений: 5,943
Записей в блоге: 27
Это я так называю любые волшебные мутаборы, которые могут указать компилятору определенное поведение, например ужимать/паковать поля структур для уменьшения размера памяти или транжирить байты ради скорости доступа.
Котовчанин
942 / 482 / 200
Регистрация: 16.02.2010
Сообщений: 3,338
Записей в блоге: 37
_Ivana, кажется, оно само это делает.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
struct T { char i = 0; char j = 0; char g = 0; char h = 0; int a = 66; int b = 77; }; void show(const char* aT, size_t size) { for (int i = 0; i size; ++i) std::cout <"i " <static_castint>(aT[i]) <"\n"; } int main() { T t; show(static_castchar*>(static_castvoid*>(&t)), sizeof(t)); system("pause>nul"); }
Вы ведь это имели в виду?
18413 / 9584 / 2341
Регистрация: 30.01.2014
Сообщений: 16,742
Сообщение от Тамика 
4816 / 2276 / 287
Регистрация: 01.03.2013
Сообщений: 5,943
Записей в блоге: 27
Сообщение от Тамика 
_Ivana, кажется, оно само это делает.
Значит у вас или по-умолчанию включены эти мутаборы, или это безмутаборное поведение по-умолчанию вообще Можно или копаться в этом, или забить. Но если забивать — то ни в коем случае не ковырять память выделенную под структуру по перекастованным указателям на чары, ожидая, что данные будут лежать вплотную
ЗЫ Как только мы ушли от ручного ассемблера к компиляторам, мы потеряли 2 важных вещи — управление временем выполнения и размещением данных в памяти. Променяли это на остальные плюшки и постепенно теряем контроль, передавая его искусственному интеллекту
18413 / 9584 / 2341
Регистрация: 30.01.2014
Сообщений: 16,742
Сообщение от Тамика 
кажется, оно само это делает.
Не оно само, а ты сама
Ты же сама расположила данные в структуре в оптимальном (для твоей платформы) порядке.
А отключение выравнивания — это другое, это если ты данные расположила не в оптимальном порядке, но выравнивать компилятор их все равно не будет. Этим обычно пользуются для формирования всякого разного рода пакетов или заголовков, предназначенных для передачи по сети, записи в файлы и т.п. Есть и обратная сторона медали — прямой доступ к невыравненным данным обычно медленее, а на некоторых аппаратных платформах в принципе невозможен (будет аппаратное исключение). Поэтому лучше этим не баловаться без нужды
Котовчанин
942 / 482 / 200
Регистрация: 16.02.2010
Сообщений: 3,338
Записей в блоге: 37
DrOffset, а я пробовала и с трёмя чариками, и с двумя, и с одним.
А вот такая штука опять меня запутала. Почему если инт первый, то под чар выделяется 4 байта. Если чар один и первый — 1 байт. Расположение на позицию кратную 4 тут не котируется, потому что инт первый.
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
struct T1 { int c = 88; char j = 0; }; struct T2 { char i = 0; }; void show(const char* aT, size_t size) { std::cout "\nNEW\n"; for (int i = 0; i size; ++i) std::cout i " " static_castint>(aT[i]) "\n"; } int main() { T1 t1; T2 t2; show(static_castchar*>(static_castvoid*>(&t1)), sizeof(t1)); show(static_castchar*>(static_castvoid*>(&t2)), sizeof(t2)); system("pause>nul"); }
Как узнать размер структуры c
sizeof(struct_obj) должен быть вроде = 4 + 4+ 2 = 10; Но C++, говорит, что 12. Объясните, пожалуйста, почему?
p.s. может быть подобная тема есть, но мобильный интернет не позволяет нормально поюзать поиск
Форумчанин
Регистрация: 11.01.2013
Сообщений: 149
Скорее всего идет выравнивание структур данных на 4 байта
Может это и чушь, но это моя чушь и я ее никому не отдам.
| Shad0wF1rst |
| Посмотреть профиль |
| Найти ещё сообщения от Shad0wF1rst |
Форумчанин
Регистрация: 24.12.2012
Сообщений: 639
ICQ: 677936656 Gmail: ekEmbed@gmail.com
| Ezhik Kihze |
| Посмотреть профиль |
| Найти ещё сообщения от Ezhik Kihze |
Регистрация: 25.10.2011
Сообщений: 3,178
Вариант 1 — выравнивание по 4 байта.
Вариант 2 — sizeof(short)==4.
| Abstraction |
| Посмотреть профиль |
| Найти ещё сообщения от Abstraction |
Форумчанин
Регистрация: 24.12.2012
Сообщений: 639
Какие варианты? Вы о чем? Я ж даже ссылку дал. Это же есть и хелпе, и в мсдн.
ICQ: 677936656 Gmail: ekEmbed@gmail.com
| Ezhik Kihze |
| Посмотреть профиль |
| Найти ещё сообщения от Ezhik Kihze |
Регистрация: 25.10.2011
Сообщений: 3,178
| Какие варианты? Вы о чем? Я ж даже ссылку дал. Это же есть и хелпе, и в мсдн. |
И? У Вас есть уверенность, что дело именно в том, что используемый ТС (неизвестный) компилятор при используемых ТС (неизвестных) настройках выравнивает структуры?
Ответ на вопрос ТС — sizeof(struct_obj) не «должен» быть равен чему-то конкретному. Стандарт C++ для большинства типов не задаёт строго их размер — это раз и не гарантирует, что sizeof для структуры равен сумме sizeof для всех членов, явно указанных в её объявлении — это два.
| Abstraction |
| Посмотреть профиль |
| Найти ещё сообщения от Abstraction |
Пользователь
Регистрация: 04.11.2012
Сообщений: 33
Использую Microsoft Visual C++ 2010. Ezhik Kihze, спасибо за ссылку.
#pragma pack(push) /* push current alignment to stack */ #pragma pack(1) /* set alignment to 1 byte boundary */ struct MyPackedData < char ID[4]; unsigned int size; unsigned short flags; >; #pragma pack(pop) /* restore original alignment from stack */
код, помог, но я не совсем могу понять, почему.. С английским не очень хорошо дела обстоят. Происходит некое выравнивание границы, но механизм всего этого не понятен. Почему при
#pragma pack(2)
, результат как при
#pragma pack(1)
Как получить размер поля структуры в си?

А без рантайм вычислений никак? На стадии компиляции.
normann ★★
( 08.09.17 15:04:02 MSK ) автор топика
Ответ на: комментарий от normann 08.09.17 15:04:02 MSK

А где здесь рантайм? O_o
Dudraug ★★★★★
( 08.09.17 15:04:36 MSK )
Ответ на: комментарий от Dudraug 08.09.17 14:58:49 MSK

В последнем варианте наверное будет более корректно использовать decltype вместо sizeof. Но так как вопрос все равно о си, то юзай первый вариант или что-то в этом роде.
Dudraug ★★★★★
( 08.09.17 15:07:56 MSK )
Последнее исправление: Dudraug 08.09.17 15:08:24 MSK (всего исправлений: 1)
Ответ на: комментарий от Dudraug 08.09.17 15:04:36 MSK
Ну да, сглупил. Всем откликнувшимся спасибо.
normann ★★
( 08.09.17 15:33:48 MSK ) автор топика
Последнее исправление: normann 08.09.17 15:34:04 MSK (всего исправлений: 1)
Ответ на: комментарий от Dudraug 08.09.17 15:07:56 MSK

Не вместо, а вместе. Весь день какую-то дичь выдаю=)
Dudraug ★★★★★
( 08.09.17 16:20:08 MSK )
Ответ на: комментарий от Dudraug 08.09.17 14:58:49 MSK
Просто на C++, любой версии, без выбоенов с std::declval:
sizeof(st::fld1)
utf8nowhere ★★★
( 08.09.17 16:38:35 MSK )
Ответ на: комментарий от normann 08.09.17 15:04:02 MSK
sizeof((struct st)<>.fld1)
utf8nowhere ★★★
( 08.09.17 16:41:20 MSK )
Ответ на: комментарий от utf8nowhere 08.09.17 16:38:35 MSK

Dudraug ★★★★★
( 08.09.17 17:30:30 MSK )
Ответ на: комментарий от Dudraug 08.09.17 17:30:30 MSK

Да ну, хипстерство. Если уж так нужно узнать, то нехай развертывает до стандартных типов, а когда получится ровно то, что в примере топика, то есть long, то уж sizeof этого то узнать можно многими способами.
Если кому интересно, то кроскомпиляторный метод определения размера типа заключается в попытке скомпилить: switch(sizeof(TYPE)) < case 4: break; case sizeof(TYPE): break; >Как ругнётся, значить угадали :))
vodz ★★★★★
( 08.09.17 18:02:56 MSK )
Ответ на: комментарий от utf8nowhere 08.09.17 16:38:35 MSK
normann ★★
( 08.09.17 18:25:01 MSK ) автор топика

Что за сборище наркоманов в этом треде изобретает sizeof?
DELIRIUM ☆☆☆☆☆
( 09.09.17 04:35:03 MSK )
Ответ на: комментарий от utf8nowhere 08.09.17 16:41:20 MSK
Это вне функции работать не будет, по-моему.
Sorcerer ★★★★★
( 11.09.17 21:11:37 MSK )
Ответ на: комментарий от Sorcerer 11.09.17 21:11:37 MSK
utf8nowhere ★★★
( 12.09.17 00:22:20 MSK )
Ответ на: комментарий от DELIRIUM 09.09.17 04:35:03 MSK

Кстати, интересная тема: изобрести sizeof. У меня получилось так:
#include struct st < long fld1; >; #define sizeof_field(type, field) \ ((size_t)((char *)(&((type *)0)->field + 1) - (char *)&((type *)0)->field)) const size_t sz = sizeof_field(struct st, fld1); int main(void)
Интересно, что здесь может пойти не так.
i-rinat ★★★★★
( 12.09.17 00:34:00 MSK )
Ответ на: комментарий от i-rinat 12.09.17 00:34:00 MSK
Интересно, что здесь может пойти не так.
6.5.3.2 (Address and indirection operators), параграф 4
The unary * operator denotes indirection. If the operand points to a function, the result is a function designator; if it points to an object, the result is an lvalue designating the object. If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.(сноска)
В сноске написано:
Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime.
Несколько слов о размере структур в С/С++ и о том, почему так получилось
Ниже по тексту термином «платформа» будем называть любой заданный набор из процессора, компилятора и операционной системы, под которой скомпилированный код будет запускаться.
- быть максимально независимым от какой-то конкретной платформы,
- быть максимально эффективным на всех платформах. В идеале — на всех.
И на весь этот зоопарк существует один-единственный Стандарт языка C. Как же это удалось? Вот тут и начинается самое интересное.
Язык C даёт очень мало ограничений на то, какими именно должны быть его базовые типы (char, short, int, long, float, double). Задаётся минимальное количество бит для некоторых типов (например, тип «char» должен быть минимум 8 бит, «int»/«short» — 16, «long» — 32), задаётся, что размеры базовых типов кратны размеру char’а, а сам размер char’а тождественно равен единице.
И, для примера: у программ под MS-DOS размер int’а и short’а совпадал, а сами эти типы были 16-битными. Для платформы Win32 размер int’а уже стал другим — 32 бита.
Немного экзотики: есть платформы (от Texas Instruments, к примеру), где размер базовых типов сильно отличается от «привычного». Например, размер всех базовых типов одинаков и равен единице. Т.е. sizeof(int)==sizeof(char)==sizeof(double). Да, именно так — и char, и short на этой платформе — 32-битные. Стандарт при этом не нарушается. Или такая платформа: тип «long» занимает в памяти 8 байт, но реально используется там только 5 Т.е. sizeof(long)==8, а ULONG_MAX=1099511627775 или 2 40 -1. Тоже это всё не противоречит Стандарту, но поначалу удивляет.
Другой важный момент из «мира железа», который обязан был учитываться при разработке Стандарта — это то, как процессор работает с памятью. Если не углубляться в то, как функционирует шина адреса, шина данных и микросхемы памяти, то для подавляющего числа архитектур существует следующее правило: если читаем/записываем одной командой N-байтовую величину, то её адрес обязан быть кратным N. То есть, если в память записывается 4-байтовый int, адрес должен делиться нацело на 4. Аналогично для 2-байтовых short’ов и т.п.
Что происходит, если это правило не выполняется? На разных платформах — по-разному: на некоторых (ARM’ы, например) происходит прерывание работы процессора и управление передаётся в ядро ОС, на других (DSP от TI) процессор просто молча запишет по ближайшему кратному адресу (т.е. не туда, куда сказали, а рядом), а на платформе x86 процессор (для некоторых типов данных) сделает так, как подразумевал программист, за счёт некоторого падения производительности. Важно тут понять одно — все процессоры работают одинаково, когда адрес является выравненным, и кто во что горазд — при невыполнении этого требования. Именно поэтому определение выравнивания (alignment) определяется в самом начале Стандарта и постоянно упоминается при описании модели памяти языка.
К чему же это всё приводит с точки зрения программиста? Лучше всего это показать на примере. Допустим, у нас есть такая структура:
struct Foo int iiii;
char c;
>;
С точки зрения программиста (неопытного) размер этой структуры равен sizeof(int)+sizeof(char)=4+1=5 (подразумеваем, что размер int’а — 4 байта). Однако, что произойдёт, если объявить массив из нескольких элементов такого типа? В памяти они будут располагаться так:
Или словами: поле iiii первого элемента располагается по выравненному адресу, а для второго элемента это уже не выполняется. Т.е. при размере структуры Foo равном 5 нельзя выполнить требования модели памяти С.
Для того же, чтобы и овцы были целы, и волки сыты, компилятор вставляет «невидимые» (для программиста) дополнительных 3 байта в конец структуры (так называемые padding bytes). Это приводит к тому, что размер структуры становится равен 8 и в памяти массив начинает располагаться так:
Однако, это ещё не всё, что делает с этой структурой компилятор. Кроме того, что размер Foo равен 8, компилятор также запоминает, что минимальное требование по выравниванию для всей этой структуры — 4 байта. Отличия легко показать на следующем примере:
struct Test1 char c;
Foo foo;
>;
Здесь интересны такие моменты: размер и Foo и Bar — одинаковый и равен 8-ми байтам. Но требования по выравниваю у Foo — 4 байта, а у Bar — 1. Это приводит к тому, что в структуре Test1, между ‘c’ и ‘foo’ компилятор вставляет дополнительных 3 байта, чтобы гарантировать, что поле ‘foo’ всегда будет начинаться по адресу, кратному 4-м. В структуре же Test2 ничего такого делать не надо, в результате — sizeof(Test1) равен 12, а sizeof(Test2) — 9. То есть получили разный результат, комбинируя «кирпичики» одного и того же размера!