Где здесь С++ (с) гость с сайта govnokod.ru
А ежели серьезно, то такие базовые вещи должен любой программист знать, который пишет на компилируемых языках программирования.
Это скорее нужно програмисту, пищущему в embedded или других средах, ограниченных по памяти. Джава программисту, пишушему для винды, будет глубоко по барабану, занимает его класс 5 или 8 байт.
Хотелось бы заметить, что размер выравнивания задается опциями компилятора. Т.е. его можно и отключить, например (MS VC 2005-2008). Думаю, что и в других компиляторах это также настраивается.
Это только в Windows зоопарк. К счастью, в Linux есть единый ABI для архитектуры и выравнивание в структурах зафиксировано в нём. Благодаря этому модули, написанные на разных языках и собранные разными компиляторами могут быть частью одной программы. А если где-то выравнивание нестандартное — этой структуры наружу API модуля не должно быть видно.
Мы же говорим о разных платформах (т.е. не обязательно даже x86 или x64) и едином стандарте. Поэтому конкретный компилятор может либо позволять задавать опции, либо использовать какое-то определенное значение. В Google Native Сlient выравнивание вообще по 16 байт, например.
Ну правильно, там система вся одним компилером, причем одной версии, собирается, какие там могут быть проблемы с ABI? Там даже по умолчанию нет никаких пакетов типа glibc-compat. То есть старые либы для совместимости вообще не тащатся
Почему-то никто до сих пор не обратил внимания на «sizeof(int)==sizeof(char)==sizeof(double). Да, именно так — и char, и short на этой платформе — 32-битные. Стандарт при этом не нарушается.»
Нарушается. Согласно «6.5.3.4 The sizeof operator»: When applied to an operand that has type char, unsigned char, or signed char, (or a qualified version thereof) the result is 1.
Тогда в чем смысл утверждения, что char — 32-битный? Что он занимает 32 бита в стеке? То же самое может быть и у компиляторов для х86, в этом ничего особого нет. Что в массиве char'ов каждый элемент занимает по 4 байта? Это уже точно противоречит.
"Semantics
The sizeof operator yields the size (in bytes) of its operand,…
When applied to an operand that has array type, the result is the total number of bytes in the array.
… EXAMPLE 1 A principal use of the sizeof operator is in communication with routines such as storage
allocators and I/O systems. A storage-allocation function might accept a size (in bytes) of an object to
allocate and return a pointer to void.
… EXAMPLE 2 Another use of the sizeof operator is to compute the number of elements in an array:
sizeof array / sizeof array[0]"
«The sizeof operator yields the size (in bytes) », всё верно, но тут тонкость в том, что этот самый «byte» определяется в пункте 1.7 Стандарта, и там нигде нет ограничения на размер этого byte'а сверху.
На той платформе, где sizeof(int)==1, этот самый byte — 32-битная величина. Меньше процессор просто не умеет.
Особенно интересно на этой платформе выглядели работа со строками и чтение файлов.
Прошу прощения, а на какой платформе 1байт = 32бита?
Я там ниже написал, у тексаса из того, что мне известно, на c28x и c54x/55x MAU=16бит, следовательно sizeof(char)=sizeof(short) = 1.
На более вменяемых msp и с64 MAU=8бит.
А Вы о какой платформе говорите?
И еще по поводу последнего примера, не думаю что так сложно заставить компилятор оптимизировать подобные структуры для минимального размера в памяти, может кто сталкивался с реализацией, и если сталкивался то в каких компиляторах?
Статья хорошая, но нет четко сформулированных выводов. Еще стоит по моему сразу писать в заголовке что речь идет о языке С, где в вопросах переносимости важно хорошо понимать принципы работы с памятью, потому что здесь это применимо конечно и реализации C++, но все же языки разные.
Никто не спорит, просто тут варианты чисто для Си, вопросы работы с выделением памяти под классы и другие тонкости связанные С++ уже отдельные темы. Просто многие могут запутаться в голове, как это часто бывает, в поиске различий работы с памятью в С и С++.
«Немного экзотики: есть платформы (от Texas Instruments, к примеру), где размер базовых типов сильно отличается от «привычного». Например, размер всех базовых типов одинаков и равен единице. Т.е. sizeof(int)==sizeof(char)==sizeof(double). Да, именно так — и char, и short на этой платформе — 32-битные.»
Что-то Вы напутали, и других же запутаете. Давайте разберёмся, не стоит «демонизировать» платформу TI :-) Вы про какие конкретно платформы от TI говорите?
char для
c28 и с54/с55 — 16бит (как и short),
msp430 и с64 — 8бит
В целом размер char определяется значением MAU (minimal addressable unit), в которых и «считает» sizeof. www-k.ext.ti.com/srvs/cgi-bin/webcgi.exe?Company={5761bcd8-11f5-4e08-84e0-8167176a4ed9},kb=dsp,case=1585,new
Спасибо за информацию — не знал. Но вот одна серьезная проблема — процессоры этих серий уже давно сняты с производства и не актуальны, и рассматривать на их примере какие-то вопросы некорректно. Хотя и допустимо, конечно, но без обобщений.
Я в общем-то спорить не собирался — хотел помочь в написании качественного материала для новичков и узнать, про какую конкретно платформу Вы говорите — у texas'а их не одна и не две. Ответ «TMS320C3x/C4x» с соответствующей правкой в тексте меня бы вполне устроил.
А пример, кстати, ужасен:)
На SPARC'е sizeof(foo)=2.
В общем два правила для тех, кто хочет не сойти с ума:
1. использовать абстрактные пользовательские платформонезависимые типы, которые определяются для каждой платформы специально.
2. не жмотничать и выравнивать всё по границе 4 байт.
И еще, к данной конкретной проблеме отношения не имеет, однако природа явления та же (демократичность и многообразие стандартов):
3. При обмене между платформами использовать функции ntohl/htonl ;-)
Несколько слов о размере структур в С/С++ и о том, почему так получилось