Практическое использование битовых полей с нулевой длиной

Я не совсем уверен в C, но C ++ допускает неназванные битовые поля длиной 0. Например:

struct X { int : 0; }; 
  • Вопрос 1. Какое практическое использование этого вы можете придумать?
  • Вопрос второй: Какие практические применения в реальном мире (если они есть) вам известны?

Отредактировал пример после ответа ледового преступления

Редактирование: Хорошо, благодаря текущим ответам я теперь знаю теоретическую цель. Но вопросы касаются практического использования, поэтому они все еще держат 🙂

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

    Реальный пример – когда NeXT портировал kernel ​​xnu из архитектуры Motorola 68000 (m68k) в архитектуру i386. У NeXT была рабочая версия m68k их ядра. Когда они портировали его на i386, они обнаружили, что требования к выравниванию i386 отличаются от m68k таким образом, что машина m68k и машина i386 не согласны с компоновкой структуры BOOTP, специфичной для поставщика NeXT. Чтобы сделать структуру структуры i386 согласованной с m68k, они добавили неназванное битовое поле с нулевой длиной, чтобы заставить структуру NV1 / nv_U быть согласованно с 16 битами.

    Вот соответствующие части из исходного кода Mac OS X 10.6.5 xnu:

     /* from xnu/bsd/netinet/bootp.h */ /* * Bootstrap Protocol (BOOTP). RFC 951. */ /* * HISTORY * * 14 May 1992 ? at NeXT * Added correct padding to struct nextvend. This is * needed for the i386 due to alignment differences wrt * the m68k. Also adjusted the size of the array fields * because the NeXT vendor area was overflowing the bootp * packet. */ /* . . . */ struct nextvend { u_char nv_magic[4]; /* Magic number for vendor specificity */ u_char nv_version; /* NeXT protocol version */ /* * Round the beginning * of the union to a 16 * bit boundary due to * struct/union alignment * on the m68k. */ unsigned short :0; union { u_char NV0[58]; struct { u_char NV1_opcode; /* opcode - Version 1 */ u_char NV1_xid; /* transcation id */ u_char NV1_text[NVMAXTEXT]; /* text */ u_char NV1_null; /* null terminator */ } NV1; } nv_U; }; 

    Стандарт (9.6 / 2) допускает только 0 бит бит-полей в качестве специального случая :

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

    Единственное использование описано в этой цитате, хотя я никогда не сталкивался с этим в практическом коде.


    Для записи я просто попробовал следующий код под VS 2010:

     struct X { int i : 3, j : 5; }; struct Y { int i : 3, : 0, j : 5; // nice syntax huh ? }; int main() { std::cout << sizeof(X) << " - " << sizeof(Y) << std::endl; } 

    Выход на моей машине действительно: 4 - 8 .

     struct X { int : 0; }; 

    неопределенное поведение в C.

    См. (Акцент мой):

    (C99, 6.7.2.1p2) «Наличие struct-declaration-list в struct-or-union-specifier объявляет новый тип внутри единицы перевода. Список struct-declaration-list представляет собой последовательность объявлений для члены структуры или объединения. Если в списке struct-declaration-list нет именованных членов, поведение не определено

    (C11 имеет ту же формулировку.)

    Вы можете использовать неназванное битовое поле с шириной 0 но не в том случае, если в структуре нет другого именованного члена.

    Например:

     struct W { int a:1; int :0; }; // OK struct X { int :0; }; // Undefined Behavior 

    Кстати, для второй декларации gcc выдает диагностику (не требуемую стандартом C) с -pedantic .

    С другой стороны:

      struct X { int :0; }; 

    определен в GNU C. Он используется, например, kernelм Linux ( include/linux/bug.h ), чтобы принудительно выполнить компиляцию с использованием следующего макроса, если условие истинно:

     #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); })) 

    Это из MSDN и не помечено как Microsoft Specific, поэтому я предполагаю, что это обычный стандарт C ++:

    Неименованное битовое поле шириной 0 принудительно выравнивает следующее поле бит на следующую границу типа, где type является типом элемента.

    Давайте будем гением компьютера.