Является ли sizeof(enum) == sizeof (int), всегда?
всегда ли sizeof(enum) == sizeof (int)?
- или это зависит от компилятора?
- неправильно ли говорить, что компилятор оптимизирован для длины слов (выравнивание памяти) ie y int-это размер слова на конкретном компиляторе? Означает ли это, что нет штрафа за обработку, если я использую перечисления, поскольку они будут выровнены по словам?
- не лучше ли мне поместить все коды возврата в перечисление, так как я явно не беспокоюсь о значениях, которые он получает, только имена при проверке возвращаемых типов. Если это так, то не #DEFINE будет лучше, так как это сэкономит память.
какова обычная практика? Если мне нужно перенести эти типы возвращаемых данных по сети, и некоторая обработка должна быть выполнена на другом конце, что бы вы предпочли enums/#defines/ const ints.
EDIT-просто проверка на net, поскольку complier не символически связывает макросы, как люди отлаживают тогда, сравнивают целочисленное значение с заголовком файл?
из ответов - я добавляю эту строку ниже, так как мне нужны разъяснения-
" Так что это реализация определена, и оператор sizeof(перечисления) может быть равна sizeof (char), т. е. 1."
- не означает ли это, что компилятор проверяет диапазон значений в перечислениях, а затем назначает память. Я так не думаю, конечно, я не знаю. Может кто-то пожалуйста, объясните мне, что такое "может быть".
5 ответов:
это зависит от компилятора и могут отличаться от перечислений. Ниже приведены семантики
enum X { A, B }; // A has type int assert(sizeof(A) == sizeof(int)); // some integer type. Maybe even int. This is // implementation defined. assert(sizeof(enum X) == sizeof(some_integer_type));
обратите внимание, что "некоторый целочисленный тип" в C99 может также включать расширенные целочисленные типы (которые реализация, однако, должна документировать, если она их предоставляет). Тип перечисления-это некоторый тип, который может хранить значение любого перечислителя (
A
иB
в данном случае).я не думаю, что есть какие-либо штрафы в использовании перечислений. Счетчики интегральные константные выражения тоже (поэтому вы можете использовать его для инициализации статических или файловых переменных области, например), и я предпочитаю их макросам, когда это возможно.
Перечислителям не нужна память времени выполнения. Только при создании переменной типа перечисления можно использовать память среды выполнения. Просто подумайте о перечислителях как о константах времени компиляции.
я бы просто использовать тип, который может хранить значения перечислителя (я должен знать примерный диапазон значений до рук), приведите его и отправьте по сети. Предпочтительно тип должен быть какой-то фиксированной ширины, например
int32_t
, поэтому он не приходит к конфликтам, когда задействованы разные машины. Или я бы напечатал номер и отсканировал его с другой стороны, что избавляет от некоторых из этих проблем.
ответ на редактирование
ну, компилятор не требуется использовать любой размер. Легко видеть, что знак значений имеет значение-беззнаковые типы могут имеют значительное повышение производительности в некоторых расчетах. Ниже приводится поведение GCC
4.4.0
на мой ящикint main(void) { enum X { A = 0 }; enum X a; // X compatible with "unsigned int" unsigned int *p = &a; }
но если вы назначаете
-1
, затем GCC выбирает использоватьint
, которыйX
совместим сint main(void) { enum X { A = -1 }; enum X a; // X compatible with "int" int *p = &a; }
используя опцию
--short-enums
GCC, что делает его использовать наименьший тип по-прежнему соответствует всем значениям.int main() { enum X { A = 0 }; enum X a; // X compatible with "unsigned char" unsigned char *p = &a; }
C99, 6.7.2. 2p4 говорит
каждый перечисленный тип должен быть совместимость с char, подписанный целочисленный тип, или без знака целочисленный тип. Выбор типа определяется реализацией,108), но должны быть способны представлять значения всех членов перечисление. [...]
сноска 108 добавляет
реализация может задержать выбор какого целого числа введите до всех перечислений константы были замечены.
таким образом, он определяется реализацией, и sizeof(enum) может быть равен sizeof(char), т. е. 1.
при выборе размера некоторого небольшого диапазона целых чисел, есть всегда штраф. Если вы сделаете его маленьким в памяти, вероятно, есть штраф за обработку; если вы сделаете его больше, есть штраф за пробел. Это пространственно-временной компромисс.
коды ошибок, как правило, определяет, что они должны быть расширяемым: различные библиотеки могут добавлять новые коды ошибок. Вы не можете сделать это с перечислениями.
это sizeof (enum) = = sizeof(int), всегда
стандарт ANSI C говорит:
каждый перечисляемый тип должен быть совместим с char, целочисленным типом со знаком или целочисленным типом без знака. Выбор типа определяется реализацией. (6.7.2.2 Enumerationspecifiers)
поэтому я бы принял это за нет.
Если это так, то не #DEFINE будет лучше, так как это сэкономит память.
каким образом использование определяет сохранение памяти при использовании перечисления? Перечисление-это просто тип, который позволяет предоставить компилятору дополнительную информацию. В фактическом результирующем исполняемом файле он просто превращается в целое число, так же как препроцессор преобразует макрос, созданный с помощью #define в его стоимости.
какова обычная практика. I если мне нужно транспортировать эти типы возвращаемых данных по сети и некоторая обработка должна быть сделано на другом конце
Если вы планируете перевозить значения по сети и обрабатывать их на другом конце, вы должны определить протокол. Определите размер в битах каждого типа, endianess (в каком порядке байты) и убедитесь, что вы придерживаетесь этого как в клиентском, так и в серверном коде. Также не просто предполагайте, что, поскольку это работает, вы все правильно поняли. Вполне возможно, что endianess, например, на выбранных вами клиентских и серверных платформах соответствует, но это может быть не всегда так.
нет.
пример: компилятор CodeSourcery
когда вы определяете перечисление следующим образом:
enum MyEnum1 { A=1, B=2, C=3 }; // will have the sizeof 1 (fits in a char) enum MyEnum1 { A=1, B=2, C=3, D=400 }; // will have the sizeof 2 (doesn't fit in a char)
подробности из списка рассылки