Чому упаковані структури не входять до мови С?


10

Кожен компілятор C пропонує можливість "упакувати" структури С (наприклад __attribute__ ((__packed__)), або #pragma pack()). Тепер ми всі знаємо, що упаковка потрібна, якщо ми хочемо надійно надсилати або зберігати дані. Це також повинно бути вимогою з перших днів мови С.

Тож мені цікаво, чому упаковані структури не входять до специфікації мови С? Їх немає навіть у C99 чи C11, хоча необхідність їх наявності відома вже десятиліттями? Що мені не вистачає? Чому саме цей компілятор?


2
Їм не потрібно писати чистий код С.
користувач253751

Відповіді:


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

@supercat: про що ти сперечаєшся (або проти)? Я не розумію.
david.pfx

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

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

0

Він специфічний для компілятора, оскільки він не входить у стандарт. І це не в стандарті, тому що було б важко вказати таким чином, що не потребуватиме великих зусиль із впровадження для компіляторів незрозумілих платформ із примусовими обмеженнями вирівнювання.

І жодне з цих зусиль не має великого виправдання, оскільки кожен компілятор / платформа, про яку піклується кожен, хто використовує компілятор C89 або пізнішої версії, вже реалізував її.


2
??? Ви відповіли на запитання "Чому немає в стандартній мові", сказавши "тому, що це не в стандарті" ...
Еміліо Гаравалія

Це я подумав спочатку, але потім ще раз можна вказати функцію типу "якщо структура визначена ключовим словом" упакована ", її розмір гарантується таким же, як доданий розмір кожного окремого члена. На платформах, які не підтримують нестандартний доступ до пам'яті, доступ до одного з значень члена структури - це невизначена поведінка. " Це дозволило б розробникам на платформах без нестандартного доступу принаймні знати розмір конструкцій та зсув кожного окремого члена ...
grasbueschel

1
Можна було б зробити роботу з нестандартним доступом у системах, які не підтримують його в апаратному забезпеченні, реалізуючи такі структури, як масив байтів і виконуючи необхідні зміщення бітів та &/ |операції для читання / запису значень кожного поля.
dan04

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