Почему упакованные структуры не являются частью языка Си?


10

Каждый компилятор C предлагает возможность «упаковать» структуры C (например __attribute__ ((__packed__)), или #pragma pack()). Теперь мы все знаем, что упаковка необходима, если мы хотим отправлять или хранить данные надежным способом. Это также должно быть требованием с первых дней языка Си.

Поэтому мне интересно, почему упакованные структуры не являются частью спецификации языка Си? Они даже не в C99 или C11, хотя необходимость их наличия известна в течение десятилетий? Чего мне не хватает? Почему это зависит от компилятора?


2
Они не нужны для написания чистого кода на C.
user253751

Ответы:


7

Я думаю, это потому, что это зависит от комбинации используемого процессора / компилятора. Это означает, что лучше быть директивой компилятора (как это связано с этим), чем языковым аспектом, потому что как это определить? Единственный способ, которым они могли бы сделать это, с союзом.

Статья Рэймонда дает некоторое представление о том, почему это так: http://www.catb.org/esr/structure-packing/


Очень интересная статья. (+1)
Джорджио

С какой трудностью можно позволить коду сказать: «Мне нужна структура, содержащая 12 байтов; поле X должно вести себя как 32-разрядное целое число, хранящееся как младший порядок в четыре октета со смещением 0; поле Y должно вести себя как 64-разрядное целое число» хранится в байтах октетов с прямым порядком байтов по смещению 4 "? Код для обработки этого на любой платформе не должен быть хуже, чем то, что компиляторы уже должны использовать для битовых полей, и в тех случаях, когда программист задает выравнивание, совпадающее с собственной машиной, может быть гораздо более эффективным. На других машинах это было бы менее эффективно, но все же переносимо.
суперкат

5

Есть три основных фактора.

  1. Некоторые процессоры не могут получить доступ к невыровненным данным (например, целое число или число с плавающей запятой, начинающееся с нечетного адреса). Попытка сделать вызывает исключение.
  2. Некоторые процессоры могут получать доступ к не выровненным данным, но за счет снижения производительности.
  3. Доступ к большинству структур осуществляется из одного набора исходного кода C / C ++, и взаимодействие с другими языками является исключением, а не правилом.

С учетом этих факторов как стандартный, так и все компиляторы C / C ++ обычно дополняют структуры, чтобы обеспечить оптимальное выравнивание для процессора, но также предоставляют механизмы для переопределения этого при необходимости для целей взаимодействия.

Это ни в коем случае не упущено из виду. Это очень хорошо понято, и текущая ситуация разработана. Последние версии стандарта C ++ имеют обширную поддержку для обработки проблем выравнивания, которые, возможно, вам не знакомы.


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

@supercat: за что вы спорите (или против)? Я не понимаю
david.pfx

Я придерживаюсь мнения, что битовые поля должны быть необязательными, но если битовые поля будут обязательной функцией, имело бы смысл расширить их таким образом, чтобы можно было явно контролировать структуру структуры. В противном случае общий эффект заключается в том, что компиляторы должны выполнять 90% работы, которая потребуется для полного контроля над макетом, но программисты получают только 10% выгоды.
суперкат

@supercat: битовые поля являются целыми числами и следуют тем же правилам упорядочивания битов, что и целые числа: реализация определена. Члены структуры упорядочены по границам символов, как объявлено, возможно со вставленной упаковкой. Концептуально они совершенно разные. [Вам нужно будет задать другой вопрос, если вы хотите расширить свое предложение, но я не думаю, что оно сработает вообще.]
david.pfx

0

Это зависит от компилятора, потому что это не в стандарте. И это не в стандарте, потому что было бы трудно указать таким способом, который не потребовал бы больших усилий по реализации для компиляторов неясных платформ с принудительными ограничениями выравнивания.

И ни одно из этих усилий не имеет большого оправдания, потому что каждый компилятор / платформа, о которой заботится любой, использующий компилятор C89 или новее, уже реализовал его.


2
??? Вы ответили на вопрос «Почему не в стандартном языке», сказав «потому что не в стандарте» ...
Эмилио Гаравалья

Сначала я подумал об этом, но с другой стороны, можно указать такую ​​функцию, как «если структура определена с ключевым словом« упакован », ее размер гарантированно будет равен добавленному размеру каждого отдельного члена. На платформах, которые не поддерживают доступ к памяти без выравнивания, доступ к одному из значений члена структуры - неопределенное поведение. " Это позволило бы разработчикам на платформах без выравниваемого доступа, по крайней мере, знать размер структур и смещение каждого отдельного элемента ...
grasbueschel

1
Было бы возможно заставить работать невыровненный доступ в системах, которые не поддерживают его аппаратно, реализовать такие структуры, как массив байтов, и выполнить необходимые операции сдвига битов и &/ |для чтения / записи значений каждого поля.
Ден04

1
@ dan04: На многих процессорах компилятор может генерировать код для выравниваемого доступа, который был бы более эффективным, чем использование последовательности считываний и сдвигов байтов. Наличие синтаксиса для этого позволило бы таким компиляторам создавать эффективный код, чем требовать, чтобы они распознавали все различные способы, которыми программисты могут пытаться писать код для сборки байтов в более длинные типы.
суперкат
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.