Переопределение базового типа перечисления с использованием прагмы или изменения кода
Проблема:
Я использую большую кодовую базу C/C++, которая работает на компиляторах gcc и visual studio, где базовый тип enum по умолчанию 32-битный (целочисленный тип).
Этот код также имеет множество встроенных сборок + встроенных, которые рассматривают enum как целочисленный тип, а данные enum используются во многих случаях как 32-битные флаги.
Когда мы скомпилировали этот код с помощью компилятора realview ARM RVCT 2.2, у нас появилось много проблем, поскольку компилятор realview автоматически определяет базовый тип перечисления на основе значения, заданного для перечисления. http://www.keil.com/support/man/docs/armccref/armccref_Babjddhe.htm
Например,
Рассмотрим перечисленное ниже,
enum Scale {
TimesOne, //0
TimesTwo, //1
TimesFour, //2
TimesEight, //3
};
Это перечисление используется как 32-битный флаг. но компилятор оптимизирует его до типа unsigned char для этого перечисления.
Использование параметра компилятора --enum_is_int не является хорошим решением для нашего случая, поскольку он преобразует все перечисления в 32-битные, что нарушает взаимодействие с любым внешним кодом, скомпилированным без --enum_is_int.
Это предупреждение, которое я нашел в компиляторах RVCT и руководстве по библиотеке,
Параметр --enum_is_int не рекомендуется для общего использования и не требуется для ISO-совместимого источника. Код, скомпилированный с этой опцией, не совместим с ABI для архитектуры ARM (базовый стандарт) [BSABI], и неправильное использование может привести к сбою во время выполнения. Эта опция не поддерживается библиотеками C++.
Вопрос
Как преобразовать весь базовый тип enum (путем внесения изменений вручную) в 32-битный, не влияя на порядок значений?
enum Scale {
TimesOne=0x00000000,
TimesTwo, // 0x00000001
TimesFour, // 0x00000002
TimesEight, //0x00000003
};
Я попробовал вышеуказанное изменение. Но компилятор оптимизирует это и для нашей неудачи.:(
В.NET есть некоторый синтаксис
enum Scale: int
Это стандарт ISO C++, а компилятору ARM его не хватает?
В компиляторе ARM RVCT 2.2 отсутствует #pragma для управления этим перечислением. Есть ли в наличии скрытая прагма?
2 ответа
Я знаю, что многие заголовки Windows используют следующее:
enum SOME_ENUM {
ONE = 1,
TWO = 2,
//...
FORCE_DWORD = 0x7FFFFFFF
};
В C++ 11:
enum class Scale : uint32_t {
TimesOne, //0
TimesTwo, //1
TimesFour, //2
TimesEight, //3
};
Visual Studio 2012 и gcc 4.4.6 с опцией -std= C++0x оба поддерживают это (более ранние версии также могут.)