Паскаль всегда поддерживал упакованные структуры, которые, вероятно, проще всего объяснить на примере
Допустим, у вас есть два массива x и y и что мы используем 16-битный процессор. То есть размер слова процессора составляет 16 бит.
myrec =
record
b : byte;
i : integer;
end;
x : array[1..10] of myrec;
y : packed array[1..10] of myrec;
Паскаль только говорит вам, что у вас есть 10 элементов для работы, каждый из которых содержит 3 байта информации (допустим, целое число - это старое 16-битное разнообразие).
Это фактически ничего не говорит о том, как эта информация хранится.
Вы можете предположить, что массив хранится в 30 последовательных байтах, однако это не обязательно верно и полностью зависит от компилятора (действительно веская причина избегать математики указателей).
Компилятор вполне может поместить фиктивный байт между значениями поля b и i, чтобы гарантировать, что и b, и i попадают на границы слов.
В этом случае структура займет всего 40 байтов.
Зарезервированное слово «упаковано» указывает компилятору оптимизировать размер по скорости, тогда как, оставляя упакованным, компилятор обычно оптимизирует скорость по размеру.
В этом случае структура будет оптимизирована и займет всего 30 байт.
Снова я говорю «мог», потому что он все еще зависит от компилятора. Ключевое слово «упаковано» просто говорит, что нужно упаковать данные ближе друг к другу, но на самом деле не говорит как.
Поэтому некоторые компиляторы просто игнорировали ключевое слово, тогда как другие использовали упакованные, чтобы отключить выравнивание слов.
В последнем случае, как правило, может происходить то, что каждый элемент выравнивается по размеру слова процессора.
Здесь вы должны понимать, что размер слова процессора - это, как правило, размер регистра, а не просто «16 бит», как это обычно происходит. Например, в случае 32-битного процессора размер слова составляет 32 бита (хотя мы в общем определяем слова как 16-битные - это просто исторический возврат)
В некотором смысле это «эквивалент памяти» сектора диска.
Упаковывая данные, вы могли бы потенциально иметь такие значения, как целочисленное пересечение границ слов, что потребовало бы большего манипулирования памятью (так же, как и необходимость чтения двух секторов диска, если запись пересекает границу сектора).
В общем, что означает изменение, так это то, что delphi теперь полностью использует упакованное ключевое слово и постоянно выполняет выравнивание байтов (по выравниванию слов).
Надеюсь, этого достаточно, чтобы объяснить это. На самом деле это большая тема, на которую я могу разумно ответить в нескольких параграфах.
ОБНОВЛЕНИЕ, продолжение цепочки комментариев ниже ...
DavidH> Я не могу представить, что вы имеете в виду, что компилятор способен выдавать различный вывод при одинаковом вводе
Да, Дэвид, это именно то, что я говорю. Не обязательно от одной компиляции к другой в одном и том же компиляторе, но, безусловно, между версиями компилятора, марками компилятора и различными платформами.
TonyH> Я думаю, что большинство из нас всегда предполагало, что упакованный = байт выровнен, поэтому сейчас мы ломаем голову над сценарием, где это не так. @ Дэвид Хеффернан спрашивает, знает ли кто-нибудь один
Тони, ты ударил гвоздь по голове здесь.
Вы предположили, что упакованный работает как директива компилятора, которая определяет, как организована память данных.
Это не то, что это значит. Лучшая аналогия - рассмотреть директиву оптимизации для генерации кода.
Вы знаете, что код оптимизируется, но вам не обязательно определенно, каким будет исходный код, и вам это не нужно.
Я могу привести множество примеров.
Допустим, у вас есть следующее (я использую массив, так же легко можно применить к записи)
myarray = packed array[1..8] of boolean
Если вы затем распечатаете SizeOf (myarray), что вы ожидаете?
Ответ заключается в том, что Delphi не гарантирует, что упакованный реализован каким-либо конкретным способом.
Поэтому ответ может быть 8 байтов (если вы выравниваете байты каждого элемента).
Delphi также может упаковывать их как биты, поэтому весь массив может уместиться в 1 байт.Это может быть 16 байт, если компилятор решит не оптимизировать границы байтов и работает на 16-битной архитектуре.
Да, это было бы менее эффективно с точки зрения скорости, но весь смысл упаковки заключается в том, чтобы оптимизировать размер по скорости.
Независимо от того, что он делает, он невидим для разработчика, если он просто обращается к элементам массива и не делает никаких предположений и пытается использовать собственную математику указателей для доступа к базовым данным.
Точно так же вы не можете даже гарантировать внутреннюю организацию примитива - он зависит от платформы, а не от компилятора. Например. Если вы работали с несколькими архитектурами, вы будете знать о проблемах, связанных с тем, сколько битов составляют целое число; хранятся ли байты в этом целом числе в байтовом порядке или в обратном байтовом порядке.
Эти типы архитектурных проблем как раз и объясняют, почему были разработаны различные методы, такие как файл с разделителями-запятыми, xml и т. Д. Чтобы обеспечить надежную общую платформу.
Подводя итог, Дэвид, проблема в том, что вы на самом деле задаете не тот вопрос. Если вы рассмотрите цитату Эмбаркадеро в контексте того, что я сказал, вы увидите, что она соответствует тому, что я говорю.