значения перечисления: NSInteger или int?

tl; dr Version

Каким образом типы данных констант перечисления гарантированно будут NSUInteger вместо unsigned int при объявлении перечисления таким образом:

enum {
    NSNullCellType = 0,
    NSTextCellType = 1,
    NSImageCellType = 2
};
typedef NSUInteger NSCellType;

typedef для NSUInteger, похоже, не привязан к объявление перечисления любым способом.

Полная версия

Я читал Apple 64-битное руководство по переходу для Cocoa , чтобы получить некоторые рекомендации по значениям перечисления, и у меня возник вопрос. Вот (длинная) цитата из раздела Константы перечисления , выделено мной:

Проблема с константами перечисления (перечисления) состоит в том, что их типы данных часто неопределенны. Другими словами, константы перечисления непредсказуемо не являются целыми числами без знака. При использовании перечислений, построенных традиционным способом, компилятор фактически устанавливает базовый тип на основе того, что он находит. Базовый тип может быть (подписанным) int или даже длинным. Рассмотрим следующий пример:

type enum {
    MyFlagError = -1,
    MyFlagLow = 0,
    MyFlagMiddle = 1,
    MyFlagHigh = 2
} MyFlagType;

Компилятор просматривает это объявление и, обнаружив отрицательное значение, присвоенное одной из констант-членов, объявляет базовый тип перечисления int. Если диапазон значений для членов не помещается в int или unsigned int, тогда базовый тип автоматически становится 64-битным (длинным). Таким образом, базовый тип величин, определенных как перечисления, может незаметно изменять размер в соответствии со значениями в перечислении. Это может произойти независимо от того, компилируете ли вы 32-битную или 64-битную версию.Излишне говорить, что такая ситуация создает препятствия для двоичной совместимости.

Для решения этой проблемы Apple решила более четко указать тип перечисления в Cocoa API. Вместо объявления аргументов в терминах перечисления файлы заголовков теперь отдельно объявляют тип для перечисления, размер которого может быть указан. Члены перечисления и их значения объявляются и присваиваются, как и раньше. Например, вместо этого:

typedef enum {
    NSNullCellType = 0,
    NSTextCellType = 1,
    NSImageCellType = 2
} NSCellType;

теперь это:

enum {
    NSNullCellType = 0,
    NSTextCellType = 1,
    NSImageCellType = 2
};
typedef NSUInteger NSCellType;

Тип перечисления определяется в терминах NSInteger или NSUInteger, чтобы сделать базовый тип перечисления 64-разрядным, совместимым с 64-разрядными архитектурами.

У меня такой вопрос: учитывая, что typedef явно не привязан к объявлению перечисления, как узнать, являются ли их типы данных беззнаковыми int или NSUInteger?

39
задан Michael Fey 13 December 2011 в 22:07
поделиться