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

10

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

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

grasbueschel
источник
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 ++ имеют обширную поддержку для обработки проблем выравнивания, которые, возможно, вам не знакомы.

david.pfx
источник
Любой аргумент, который может быть сделан против упакованных структур, также может быть использован для оправдания превращения битовых полей в необязательную функцию. Доступ к членам упакованных структур будет медленным на некоторых процессорах, быстрым на других, но наличие компиляторов, пытающихся заменить обходные пути пользовательского кода из-за отсутствия функций выравниваемого доступа более эффективным кодом, гораздо сложнее, чем просто наличие компиляторов, позволяющих программистам определять, что им нужно.
суперкат
@supercat: за что вы спорите (или против)? Я не понимаю
david.pfx
Я придерживаюсь мнения, что битовые поля должны быть необязательными, но если битовые поля будут обязательной функцией, имело бы смысл расширить их таким образом, чтобы можно было явно контролировать структуру структуры. В противном случае общий эффект заключается в том, что компиляторы должны выполнять 90% работы, которая потребуется для полного контроля над макетом, но программисты получают только 10% выгоды.
суперкат
@supercat: битовые поля являются целыми числами и следуют тем же правилам упорядочивания битов, что и целые числа: реализация определена. Члены структуры упорядочены по границам символов, как объявлено, возможно со вставленной упаковкой. Концептуально они совершенно разные. [Вам нужно будет задать другой вопрос, если вы хотите расширить свое предложение, но я не думаю, что оно сработает вообще.]
david.pfx
0

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

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

Сору
источник
2
??? Вы ответили на вопрос «Почему не в стандартном языке», сказав «потому что не в стандарте» ...
Эмилио Гаравалья
Сначала я подумал об этом, но с другой стороны, можно указать такую ​​функцию, как «если структура определена с ключевым словом« упакован », ее размер гарантированно будет равен добавленному размеру каждого отдельного члена. На платформах, которые не поддерживают доступ к памяти без выравнивания, доступ к одному из значений члена структуры - неопределенное поведение. " Это позволило бы разработчикам на платформах без выравниваемого доступа, по крайней мере, знать размер структур и смещение каждого отдельного элемента ...
grasbueschel
1
Было бы возможно заставить работать невыровненный доступ в системах, которые не поддерживают его аппаратно, реализовать такие структуры, как массив байтов, и выполнить необходимые операции сдвига битов и &/ |для чтения / записи значений каждого поля.
Ден04
1
@ dan04: На многих процессорах компилятор может генерировать код для выравниваемого доступа, который был бы более эффективным, чем использование последовательности считываний и сдвигов байтов. Наличие синтаксиса для этого позволило бы таким компиляторам создавать эффективный код, чем требовать, чтобы они распознавали все различные способы, которыми программисты могут пытаться писать код для сборки байтов в более длинные типы.
суперкат