- 1
- 2
Comparing structs with, let's say, memcmp, does not work,
as you end up comparing the "unspecified" padding bytes as well — you must compare member-by-member.
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
+2
Comparing structs with, let's say, memcmp, does not work,
as you end up comparing the "unspecified" padding bytes as well — you must compare member-by-member.
While writing this post, the author observed that some verions of GCC (experimentally, >= 4.7, < 8.0) do not zero padding if an empty intializer list is passed, under certain a certain code pattern; if an entire struct (i.e. sizeof(STRUCTNAME)) is subsequently memcpy'd after assigment of its members, and this intermediate buffer is what is used by the code going forward. This appears to be based on how optimization passes interact with GCC's built-in memcpy, since passing -fno-builtin-memcpy returns the behavior to the expected.
https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2019/october/padding-the-struct-how-a-compiler-optimization-can-disclose-stack-memory/
И инициализировать через этот говномассив нулями. Тогда там все эти говнопаддинги занулиться должны
А должны ли?)
На всякий случай, в GCC предусмотрена особая хуйня __attribute__ ((may_alias))
Видишь как всё просто
Проблема в том что когда мы начнём писать в поля значения, компилеру ничего не помешает опять засрать паддинги ворециями.
Допустим мы пишем uint8_t а и uint8_t с. А компилер джва присваивания оптимизирует в один mov с мусором в паддинге.
Ниже по треду bormand уже пояснял.
Не, ну ясен хер что это говно и костыли, в крестах кстати type punning через union это вообще UB.
>каст структуры в структуру
>>цари
>>структуры
Это несовместимые понятия.
Повторюсь:
Цари используют массивы, единственно полезную структуру данных.
В массивах паддинга нет by design.
Т. е. если у нас struct {int coq; char rooster; double xuroz;} petuh[100500]; то это можно заменить на int petuh_coq[100500]; char petuh_rooster[100500]; double petuh_xuroz[100500];
При итерации по таким массивам не будет ни дурацких паддингов, ни хромого шага.
Хотя возможно, я фигню написал, и это не имеет значения. Нужно смотреть конкретную задачу, чтобы понять, что и в каком порядке нам придётся доставать из массива.
Только вот может быть всякая хуйня с кешмиссами
http://govnokod.ru/5286#comment69576
И тогда проблем нет. Осталось изобрести метушню на крестоговне, которая эти паддинги нагенерирует.
Цари используют массивы, единственно полезную структуру данных.
Что там кстати стандарт говорит насчет выравниваний для базовых типов? Может ли быть ситуация, что int у нас 5-байтный, но требование к выравниванию у него 2 байт, и тогда с массивом получится хуита вида
?
Тогда и без структур будут паддинги
Дык там паддинги будут в самих структурах, а не между элементами массива...
> int 5-байтный
Х.з., конкретной формулировки не нашёл. Но там написано, что int'ы могут содержать padding биты. Т.е. скорее всего твоё выравнивание на 2 байта будет встроено внутрь самого int'а. Но это не точно.
Типа
char* pituh = malloc(100); double cock; memcpy(&cock, pituh + 1, sizeof(cock));
Интересно, такая хуйня где-нибудь используется?
А где я такое заявлял? Мантисса отдельно, экспонента отдельно, знаковый битик отдельно. http://www.softelectro.ru/ieee754.html
Поэтому кстати в плавучих 754-х питухах есть отрицательный и положительный ноль, в отличии от знаковых целочисленных питухов в дополнительном коде(two’s complement), где такой хуйни нет.
А вот беззнаковых плавучих 754-х питухов не завезли к сожалению, поэтому на каждого такого питуха будет тратиться целый лишний бит
1/32 = 3,125%
1/64 = 1,5625%
1/80 = 1,25%
Так себе экономия. Зато потеря пирфоманса от упаковки/распаковки. Разве что для архивного формата пойдёт.
У меня другое предложение: добавить этот бит к мантиссе либо к порядку, чтобы расширить точность или диапазон. У целых чисел этот бит как раз расширяет верхнюю границу. Да, получится плавающий питух, не полностью совместимый с IEEE 754.
Это же отрыжка 8087, на нормальных платформах старым говном не пользуются, там есть нативная поддержка banaly64
Выравнивание должно быть степенью двойки:
(§6.11/4)
У char'ов оно должно быть самым маленьким:
(§6.11/5,6)
А вот про выравнивание остальных фундаментальных типов я не нашёл ничего, кроме намёка на то, что оно есть:
(§6.9.1/3)
Превращает простейшие вещи в унылое оопешное шарпожабство с необходимостью писать ручные equalsы на каждое поле, сеттеры и копирующие конструкторы.
Выберёт из джвух вариантов:
1) NaN == NaN //always false
2) UB
Ручками писать сравнения каждого поля.
А флоаты никто не сравнивает через ==. Это делают через эпсилон, как учили в школе.
C опциональной обработкой NaNа согласно логике кода.
Тарас же для игр использовал сугубо флоаты, потому прекрасно понимал что memcmp это кулцхакирство.
Это кроссязыковое свойство между прочим.
Браузер от такого сравнения тоже почему-то не падает.
Никак не могу запомнить, зачем этот знак нужен в «Ruby».
Все операции сравнения с NaN возвращают false.
Кроме !=
Это записано не в сишном стандарте, а стандарте для флоатов: IEEE 754.
Потому оно по идее должно быть однородно во всех языках.
А в остальных языках сравнивать плавающих питухов на точное равенство нельзя. Даже в «PHP».
«Патамучто это плавающий питух, который априори говно. И чем вы быстрее это поймёте, чем будет лучше.» ⓒ
http://govnokod.ru/13189#comment182595
Тем не менее, у типа real были значения -0 и +0, а сравнивать на равенство тоже приходилось через эпсилон.
Шутку не знаю.
Если не указать знак типа, то может создаться целочисленная переменная (ну типа как в старой сишке, если не указать тип, то будет int).
Не. Этот новодел уже в QB завезли.
В олдбейсике, том что с метками, такое не работало. Только значок доллара для строк.
MID$, LEFT$
А других суффиксов я не припоминаю.
Я кажется экспериментировал с другими значками (документации ведь не было), вроде они все падали с ошибкой.
Может какой-то другой, более поздний диалект. Но кроме QB я больше такого нигде не видел.
>был же такой?
Был. И не у одного тебя.
Бейсик (ещё до мелкомягких) во многом вырос именно из фортрана.
Строки-метки, операторы типа IF X THEN a где a — номер метки; динамическая типизация, пресловутый god is real.
Причём, если в фортране были целые, то в бейсике не стали заморачиваться, и сделали всё даблами. Впоследствии js заимствовал эту парадигму.
ANDы и ORы по каким-то хитрым, неявным правилам конвертились в целые. Прям как в яваскрипте.
We made no distinction between floating-point arithmetic; we used only double precision floating-point internally, and adopted several strategies to make loop termination come out right.
DIMENSION ARR(3,4)
DIM ARR(3,4)
Реализацию чисел в разных бейсиках не изучал. Помню только, что операции целочисленного деления и вещественного явно различались (для целочисленного использовался обратный слэш).
В «Кубейсике», как я уже заметил, целые и вещественные различались явно. Для переменных использовались разные суффиксы (%, !, &, #) либо директивы DEFINT/DEFSNG/DEFLNG/DEFDBL (для любителей венгерки) либо спецификаторы в выражении DIM (DIM AS INTEGER, DIM AS SINGLE, DIM AS LONG, DIM AS DOUBLE).
Целые и вещественные были ещё где-то разделены, помимо «Кубейсика». Я уже отметил суффиксы % и !, но точно не вспомню, в каких реализациях они поддерживались. Придётся перебирать.
В реализациях, которыми я пользовался, AND и OR можно было использовать только в выражении IF. То есть булев тип ни во что не кастовался и даже сохранить его в переменной было нельзя. Вот так булев тип был ущемлён в правах.
Applesoft BASIC: был суффикс % для целого питуха; булев тип кастовался в целые.
http://wiki.apple2.org/index.php?title=Applesoft_BASIC_Ref#Nume ric_Expressions_and_Assignments:
GW-BASIC: четыре типа числовых переменных, как в «Кубасике».
https://hwiegman.home.xs4all.nl/gw-man/index.html
BBC BASIC: есть суффикс % для целого питуха.
http://www.bbcbasic.co.uk/wiki/doku.php?id=number_20conversion_20in_20b asic
Вильнюсский Бейсик (БК-0010): три типа числовых переменных (суффикс % для целых и суффиксы ! и # для двух типов плавающих питухов).
http://www.emuverse.ru/wiki/УКНЦ_Бейсик_Описание_языка
Вот Sinclair Basic целых и плавающих питухов не различал.
Это и есть «Quick Basic», который я упоминал раньше.
>> бейсики для spectrum
Это «Sinclair BASIC».
Остальные нужно проверить, да.
https://www.atariarchives.org/basic/showpage.php?page=53
«Commodore BASIC»: был суффикс % для целых, в противном случае питух считался плавающим. Булев тип кастовался в целый.
http://www.zimmers.net/cbmpics/cbm/c65/c65manual.txt
В «UBASIC» был суффикс % для «маленьких» чисел (они назывались short variables; занимали одно машинное слово) и # для «больших» чисел (они назывались extra variables; могли вместить до 540 машинных слов). Причём одна и та же переменная могла хранить целое число, рациональное, вещественное, комплексное или многочлен. Да, различались рациональные и вещественные, а так же в переменной можно было хранить многочлен одной переменной (лямбды в Бейсике, ужас).
ftp://ftp.bu.edu/mirrors/simtelnet/msdos/ubasic/
В документации по «Amiga BASIC» нашёл суффиксы %, !, # на 197-й странице:
https://archive.org/download/AmigaBasic
«Power BASIC» был сильно перегружен. Для числовых переменных была куча суффиксов:
Byte (?)
Word (??)
Integers (%)
Double-word (???)
Long integers (&)
Quad integers (&&)
Single-precision floating-point (!)
Double-precision floating-point (#)
Extended-precision floating-point (##)
Currency (@)
Extended-currency (@@)
Не сильнее чем современные кресты и хаскели.
А если она после имени переменной, то в некоторых реализациях она означает большого плавающего питуха (double или типа того).
У «Бейсика» тоже были свои типы плавающих питухов. Гугли MBF (Microsoft binary format).
Операции с типами IEEE754 переключались на хардварные, если процессор их поддерживал (модуль SYSTEM проверял это при старте программы), а вот операции с типом real всегда оставались софтварными, потому что ни один проц такой царский тип не поддерживал.
макака думала, что real это у них был double
Кстати, о разницах между реализациями питуха
Знаешь такой бугор
https://en.wikipedia.org/wiki/Strictfp
?
Про strictfp что-то слышал, но пока не копал этот вопрос.
Во-1. Для 100500 полей есть массивы. Нет, я серьёзно.
Во-2. В жабамире уже давно никто ничего вручную не сравнивает, @lombok.EqualsAndHashCode
https://projectlombok.org/features/EqualsAndHashCode
Там два десятка правил, как правильно сравнивать. И парочка исключений из этих правил.
Список pitfalls по твоей ссылке достойный, но там есть ещё парочка: типа невозможности найти объект с мутабельными полями в хеш-мапе, плюс те же флоаты.
Блох вопросу equals посвятил треть своей книжки.
Потому никто их руками обычно не пишет, а либо генерируют через IDE, либо @lombok.EqualsAndHashCode.
Если данные разнородные, то просто будет паддинг до интов.
В сишке есть дико идиоматичная инициализация массивов, подобная структурам.
И в сишке есть енумы c опциональной автонумерацией.
Адресация идёт строго через енум, никаких магических цифр.
Ну и соответственно никто не мешает делать memcpy, memcmp и прочие царизмы.
Ага. Вот это просто суперидиоматичная фича сишки.
http://govnokod.ru/24276
А у массивов паддинга нет by design.
https://godbolt.org/z/dPHBkb
Мусор зануляется.
Добавь -fno-builtin-memcpy и тогда из паддингов пропадёт мусор: 7F 05 05
http://govnokod.ru/9686#comment132740
https://gcode.space/ngk/#!/search?user=TheCalligrapher