Pull to refresh

Comments 53

UFO just landed and posted this here
UFO just landed and posted this here
Об очевидности вещей, как правило, говорят люди, которые сами не так давно об этих вещах узнали.
Это же касается и обзывательства «школотой», кстати.
И «обаяниванием» тоже, кстати.
Вы правы.
UFO just landed and posted this here
Отличная статья!
Ничего лишнего, легко читается =)
Спасибо!
UFO just landed and posted this here
MikhailEdoshin, пожалуйста, не продолжайте :)
UFO just landed and posted this here
Чем больше таких статей, тем больше «Хабр еще торт».
В целом статья понравилась, хорошо написана, однако про выравнивание на хабре писали уже не раз.
Повторенье — мать ученья.
Где здесь С++ (с) гость с сайта govnokod.ru
А ежели серьезно, то такие базовые вещи должен любой программист знать, который пишет на компилируемых языках программирования.
Это скорее нужно програмисту, пищущему в embedded или других средах, ограниченных по памяти. Джава программисту, пишушему для винды, будет глубоко по барабану, занимает его класс 5 или 8 байт.
Джава-программисту, пишущему на С++?
который пишет на компилируемых языках программирования.

Читайте коммент выше.
Можно было добавить про pragma/attribute packed ;)
Да я про это и собирался писать изначально.

Но как рассказать про #pragma pack, не рассказав перед этим, что такое вообще выравнивание и на что именно оно влияет?
Хотелось бы заметить, что размер выравнивания задается опциями компилятора. Т.е. его можно и отключить, например (MS VC 2005-2008). Думаю, что и в других компиляторах это также настраивается.
Это только в Windows зоопарк. К счастью, в Linux есть единый ABI для архитектуры и выравнивание в структурах зафиксировано в нём. Благодаря этому модули, написанные на разных языках и собранные разными компиляторами могут быть частью одной программы. А если где-то выравнивание нестандартное — этой структуры наружу API модуля не должно быть видно.
Мы же говорим о разных платформах (т.е. не обязательно даже x86 или x64) и едином стандарте. Поэтому конкретный компилятор может либо позволять задавать опции, либо использовать какое-то определенное значение. В Google Native Сlient выравнивание вообще по 16 байт, например.
Ну правильно, там система вся одним компилером, причем одной версии, собирается, какие там могут быть проблемы с ABI? Там даже по умолчанию нет никаких пакетов типа glibc-compat. То есть старые либы для совместимости вообще не тащатся
Эх, забыл я много. Последний раз занимался этой машинерией при маршалинге данных в .NET.
Я начинающий (хм, «неопытный»:) ) программист, и мне это интересно. Хотел бы продолжения :)
Спасибо за топик. Кратко и толково. Если продолжите в том же духе, будет просто замечательно.
Когда я только начинал читать книжку по С++, то сразу обратил внимания на всё это, потому что на данную тему там было выделено около 10 страниц :)
Почему-то никто до сих пор не обратил внимания на «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.
Между sizeof(char) == 1 и char — 32-битный нет противоречия в общем случае.
Тогда в чем смысл утверждения, что 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]"
Байт (как минимальная единица обрабатываемой информации) там 32-битный просто. 8-битных значений как таковых нет.
«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бит.
А Вы о какой платформе говорите?
Довольно интересно, даже учитывая что я не люблю писать на С.
И еще по поводу последнего примера, не думаю что так сложно заставить компилятор оптимизировать подобные структуры для минимального размера в памяти, может кто сталкивался с реализацией, и если сталкивался то в каких компиляторах?
снова вы?
нет, мы не собираемся покупать PVS-Stduio, хотя и прекрасно осведомлены о нем.
UFO just landed and posted this here
Статья хорошая, но нет четко сформулированных выводов. Еще стоит по моему сразу писать в заголовке что речь идет о языке С, где в вопросах переносимости важно хорошо понимать принципы работы с памятью, потому что здесь это применимо конечно и реализации C++, но все же языки разные.
Всё, что здесь написано, одинаково что для 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
Вот платформа SPARC от Analog Devices: www.analog.com/static/imported-files/software_manuals/50_21k_cc_man.rev1.2.pdf

Таблица 1-13, «Data Type and Data Type Sizes». Размер всех типов (за исключением long double) — 32 bits, возвращаемое sizeof значение — 1.

У TI должно быть что-то похожее, но я что-то сейчас не смог найти.
А причем тут AD?
Вы же про texas написали.

доки на компиляторы:
msp430 — slau132c
c28 — spru514c
c55 — spru281e
c54 — spru103g
tms320c6000 — spru187q

Ищите, сверяйте, исправляйте…
Настырный какой!

www.ti.com/litv/pdf/spru034h — платформа TMS320C3x/C4x, таблица 3-1
Все типы (кроме long double) — 32-бита.

Там же, прямым текстом: «A TMS320C3x/C4x Byte Is 32 Bits»
Спасибо за информацию — не знал. Но вот одна серьезная проблема — процессоры этих серий уже давно сняты с производства и не актуальны, и рассматривать на их примере какие-то вопросы некорректно. Хотя и допустимо, конечно, но без обобщений.

Я в общем-то спорить не собирался — хотел помочь в написании качественного материала для новичков и узнать, про какую конкретно платформу Вы говорите — у texas'а их не одна и не две. Ответ «TMS320C3x/C4x» с соответствующей правкой в тексте меня бы вполне устроил.
Вы забыли про 8-битные контроллеры! Для них С и С++ стандарты те-же и должны выполнятся…
А пример, кстати, ужасен:)
На SPARC'е sizeof(foo)=2.

В общем два правила для тех, кто хочет не сойти с ума:
1. использовать абстрактные пользовательские платформонезависимые типы, которые определяются для каждой платформы специально.
2. не жмотничать и выравнивать всё по границе 4 байт.

И еще, к данной конкретной проблеме отношения не имеет, однако природа явления та же (демократичность и многообразие стандартов):
3. При обмене между платформами использовать функции ntohl/htonl ;-)
Only those users with full accounts are able to leave comments. Log in, please.