Является ли sizeof(enum) == sizeof (int), всегда?


всегда ли sizeof(enum) == sizeof (int)?

  • или это зависит от компилятора?
  • неправильно ли говорить, что компилятор оптимизирован для длины слов (выравнивание памяти) ie y int-это размер слова на конкретном компиляторе? Означает ли это, что нет штрафа за обработку, если я использую перечисления, поскольку они будут выровнены по словам?
  • не лучше ли мне поместить все коды возврата в перечисление, так как я явно не беспокоюсь о значениях, которые он получает, только имена при проверке возвращаемых типов. Если это так, то не #DEFINE будет лучше, так как это сэкономит память.

какова обычная практика? Если мне нужно перенести эти типы возвращаемых данных по сети, и некоторая обработка должна быть выполнена на другом конце, что бы вы предпочли enums/#defines/ const ints.

EDIT-просто проверка на net, поскольку complier не символически связывает макросы, как люди отлаживают тогда, сравнивают целочисленное значение с заголовком файл?

из ответов - я добавляю эту строку ниже, так как мне нужны разъяснения-

" Так что это реализация определена, и оператор sizeof(перечисления) может быть равна sizeof (char), т. е. 1."

  • не означает ли это, что компилятор проверяет диапазон значений в перечислениях, а затем назначает память. Я так не думаю, конечно, я не знаю. Может кто-то пожалуйста, объясните мне, что такое "может быть".
5 54

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)

подробности из списка рассылки

на некоторых компиляторах размер перечисления зависит от того, сколько записей находится в перечислении. (менее 255 записей = > байт, более 255 записей int) Но это зависит от компилятора и настроек компилятора.