Почему стандарт не требует, чтобы члены структуры были дополнены минимально? - PullRequest
0 голосов
/ 01 июня 2018

Стандарт не предъявляет каких-либо требований к заполнению для элементов структуры, даже если он запрещает переупорядочение (6.7.2.1p6) .Насколько вероятно, что платформа C не будет дополнять минимально, то есть не будет добавлять только минимальное количество отступов, необходимое для того, чтобы следующий элемент (или экземпляр той же структуры, если это последний элемент) был достаточно выровнен для егоtype?

Имеет ли смысл в стандарте не требовать минимального заполнения?

Я спрашиваю, потому что это отсутствие гарантии заполнения, по-видимому, не позволяет мне переносить представление сериализованных объектов в виде структур (даже если я ограничиваю себя только uint8_t массивами в качестве членов, компиляторы, похоже, могут добавлятьмежду ними), и я нахожу немного странным прибегать к арифметике там.

1 Ответ

0 голосов
/ 02 июня 2018

Насколько вероятно, что платформа C не будет заполняться минимально, т. Е. Не будет добавляться только минимальное количество отступов, необходимое для проверки следующего члена (или экземпляра той же структуры, если это последний член)) достаточно выровнен по своему типу?

По сути, "дополнительные" отступы могут позволить существенную оптимизацию компилятора.

К сожалению, я не знаю, действительно ли какой-либо компилятор делает это (и, следовательно, не может предоставить какую-либо оценку вероятности его возникновения.)

В качестве простого примера рассмотрим 32-разрядную или 64-разрядную архитектуру, где ABI утверждает, что строковые литералы и символьные массивы выровнены по 32-бит или 64-битная граница.Многие из функций библиотеки C (также) реализованы самим компилятором C;см. например эти списки для GCC .Компилятор может отслеживать параметры, чтобы увидеть, ссылаются ли они на строковый литерал или (начало a) символьного массива, и, если это так, заменить, например, strcmp() на оптимизированную встроенную версию (которая выполняет сравнение в 32-разрядной версии).единиц, а не char-at-a-time).

В качестве более сложного примера рассмотрим аппаратную архитектуру RISC, в которой доступ к не выровненному байту медленнее, чем доступ к выровненному собственному слову.(Например, первый может быть реализован в аппаратном обеспечении как последний, за которым следует сдвиг битов.) Такая архитектура может иметь ABI, который требует, чтобы все элементы структуры были выровнены по словам.Затем компилятору C потребуется добавить больше, чем минимальное заполнение.

Традиционно комитет по стандартам C очень тщательно следит за тем, чтобы не исключать какую-либо аппаратную архитектуру для правильной реализации языка.

Разумно ли в стандарте не требовать минимального заполнения?

Раньше цель стандарта C заключалась в том, чтобы гарантировать, что код C будет вести себя одинаково при компиляции с различными компиляторами, и разрешить реализацию языка на любой достаточно способной аппаратной архитектуре.В этом смысле очень разумно для стандарта не требовать минимального заполнения, поскольку некоторые ABI могут потребовать более минимального заполнения по любой причине.

С введением Microsoft "extensions" , цель стандарта C значительно сместилась, чтобы связать C с C ++, чтобы компилятор C ++ мог компилировать код C с минимальными отличиями от компиляции C ++, и предоставлять интерфейсы, которые можно продавать как "более безопасные""с реальной целью балканизации разработчиков и привязки их к реализации одного поставщика.Поскольку это противоречит предыдущему назначению стандарта и явно не разумно стандартизировать функции одного поставщика, такие как fscanf_s (), но не стандартизировать функции многих поставщиков, такие как getline (), это может неможно определить, что sensible означает больше в контексте стандарта C.Это определенно не соответствует «здравому смыслу»;теперь это, вероятно, относится к «восприятию чувствами».

Я спрашиваю, потому что это отсутствие гарантии заполнения, кажется, мешает мне переносить представление сериализованных объектов как структуры

Вы повторяете одну и ту же ошибку, которую делают программисты на С снова и снова.Структуры не подходят для представления сериализованных объектов.Вы не должны использовать структуру для представления сетевого объекта или заголовок файла из-за правил структуры C.

Вместо этого вы должны использовать простой символьный буфер и любые функции доступа(для извлечения или упаковки каждого элемента или поля из буфера) или функции преобразования (для преобразования содержимого буфера в структуру и наоборот).

Основная причина, по которой даже опытные программисты, такие как asker, все еще предпочитаютвместо этого использовать структуру, это то, что средства доступа / преобразования включают в себя много дополнительного кода;вместо этого было бы лучше, если бы компилятор делал это: было бы меньше кода, проще и проще в обслуживании.

И я согласен.Было бы даже очень просто, если бы было введено новое ключевое слово, скажем, serialized_struct;представить сериализованную структуру данных с совершенно другими правилами-членами традиционных структур Си.(Обратите внимание, что эта поддержка не будет влиять, например, на связывание, поэтому она на самом деле не так сложна, как можно подумать.) Дополнительные атрибуты или ключевые слова могут использоваться для указания явного порядка байтов, и компилятор сделает все детали преобразования для нас.в любом случае, компилятор лучше всего подходит для конкретной архитектуры, для которой он предназначен.Эта поддержка будет доступна только для нового кода, но она будет чрезвычайно полезна для сокращения проблем совместимости - и это упростит большую часть кода сериализации!

К сожалению, когда вы объединяете комитет по стандартизации CТрадиционная неприязнь к добавлению новых ключевых слов и общему изменению направления от функциональной совместимости к привязке к поставщикам вообще не дает шансов на включение чего-либо подобного в стандарт C.

Конечно, как описано вкомментарии, есть много библиотек C, которые реализуют одну или несколько схем сериализации.Я даже написал несколько сам (хотя для довольно специфических случаев использования).Разумным подходом (плохая игра слов) было бы выбрать живой (ухоженный, с оживленным сообществом вокруг библиотеки) и использовать его.

...