Расширение GCC / Clang / MSVC для указания размера перечисления C?

#c #compiler-construction #enums #size

#c #конструкция компилятора #перечисления #размер

Вопрос:

Существует ли какая-либо функция расширения для указания размера C enum в каждом компиляторе?

  • GCC
  • Clang
  • MSVC

Ответ №1:

С помощью GCC вы не можете указать точную длину, но вы можете заставить ее занимать максимально короткую длину с -fshort-enums . Пример:

 #include <stdio.h>

typedef enum
{
    f1, f2
} foo;

int main()
{
    printf("%in", sizeof(foo));
    return 0;
}
  

Скомпилировать:

 gcc program.c -fshort-enums
  

Вывод:

 1
  

Однако, если вы когда-нибудь захотите создать ссылку на что-либо, вы должны убедиться, что тот, кто просматривает ваши заголовки, также использует -fshort-enums , иначе это не будет совместимо с ABI (и вы увидите несколько действительно забавных ошибок).

Комментарии:

1. Я должен также отметить, что clang такой функции нет. Я сомневаюсь, что MSVC это делает, но я не знаю наверняка. Обычно считается плохой практикой использовать переключатели компилятора для переопределения размера типов, и, как правило, лучше всего упаковывать биты самостоятельно.

2. Лучше использовать атрибут gcc, упакованный на основе перечисления по перечислениям. —короткие перечисления могут иметь неожиданные последствия для заголовков, включенных из сторонних библиотек. ( oroboro.com/short-enum )

Ответ №2:

В C 11 представлен стандартизированный способ сделать это, но поскольку это C, вам придется довольствоваться более простым методом создания последнего перечисления INT_MAX или значением, достаточно большим, чтобы его мог содержать только нужный вам тип (это то, что делает DirectX SDK). К сожалению, нет способа принудительно установить максимальный размер (по крайней мере, без расширений, специфичных для компилятора).

Ответ №3:

С clang вы можете использовать это:

 enum Tristate : char { Yes, No, Maybe };
  

Если вы хотите typedef , убедитесь, что вы включили спецификатор размера как для enum , так и для typedef определения:

 enum Tristate : char { Yes, No, Maybe };
typedef enum Tristate : char Tristate;
  

В противном случае вы получите предупреждение компилятора.

Или вы определяете анонимный enum и typedef напрямую:

 typdef enum : char { Yes, No, Maybe } Tristate;