Подтвердить что ты не робот

Почему cocoa не использует один и тот же стиль декларации перечисления во всем мире?

Мне было интересно, в чем смысл разных стилей объявления enum на cocoa?

Вот так:

enum { constants.. }; typedef NSUInteger sometype;

Является ли причина использования typedef для получения привязок к NSUInteger для работы без кастинга?

Иногда typedef является либо NSInteger/NSUInteger, почему бы не использовать NSInteger всегда? Есть ли реальная польза от NSUInteger?

Тэги Enum по-прежнему используются иногда, например здесь в _NSByteOrder.

Этот ответ был очень полезен: Что такое перечисление typedef в Objective-C?.

4b9b3361

Ответ 1

Несколько причин:

Причина 1: Гибкость:

enum lickahoctor { yes = 0, no = 1, maybe = 2 };

объявляет перечисление. Вы можете использовать значения yes, no и maybe в любом месте и назначить их любому интегральному типу. Вы также можете использовать это как тип, написав

enum lickahoctor myVar = yes;

Это хорошо, потому что если функция принимает параметр с типом enum lickahoctor, вы узнаете, что вы можете назначить ему yes, no или maybe. Кроме того, отладчик будет знать, поэтому он будет отображать символическое имя вместо численного значения. Проблема заключается в том, что компилятор позволит вам назначать значения, определенные вами в enum lickahoctor, на myVar. Если вы, например, хотите определить несколько флагов в базовом классе, добавьте еще несколько флагов в подкласс, вы не сможете сделать это таким образом.

Если вы используете int вместо этого, у вас нет этой проблемы. Поэтому вы хотите использовать какой-то int, поэтому вы можете назначить произвольные константы.

Причина 2: двоичная совместимость:

Компилятор выбирает хороший размер, который соответствует всем константам, которые вы определили в перечислении. Там нет гарантии того, что вы получите. Поэтому, если вы пишете структуру, содержащую такую ​​переменную, непосредственно в файл, нет никакой гарантии, что она будет по-прежнему иметь тот же размер, когда вы ее прочитаете в следующей версии вашего приложения (в соответствии со стандартом C, по крайней мере, - это не совсем то, что мрачно на практике).

Если вы используете какой-то тип int, платформа обычно гарантирует определенный размер для этого числа. Особенно, если вы используете один из типов, гарантированных определенным размером, например int32_t/uint32_t.

Причина 3: читаемость и самостоятельная документация

Когда вы объявляете myVar выше, сразу видно, какие значения вы можете вставить в него. Если вы просто используете int или uint32_t, это не так. Итак, что вы делаете, вы используете

enum { yes, no, maybe };
typedef uint32_t lickahoctor;

чтобы определить красивое имя для целого числа где-то рядом с константами, которые будут напоминать людям, что переменная этого типа может удерживать это значение. Но вы по-прежнему пользуетесь предсказуемым фиксированным размером и возможностью определять дополнительные значения в подклассах, если это необходимо.

Причина 4: Поддержка битполей

Переменные, перечисленные только переменные, поддерживают только назначение одного значения из своих опций. Поэтому, если вы пытаетесь реализовать бит-бит, вы не можете вводить его как бит-поле. Кроме того, вам нужно использовать неподписанные переменные, чтобы избежать расширения расширений.

Ответ 2

Является ли причина использования typedef для получения привязки к NSUInteger для работы без литья?

typedef используется для указания базового типа для значений перечисления. Вы всегда можете присвоить значение перечисления другому типу, если вы усекаете значение, путем литья на меньший тип (NSUInteger до unsigned short).

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

Иногда typedef является либо из NSInteger/NSUInteger, почему бы не использовать NSInteger всегда? Есть ли реальные использовать NSUInteger?

Выбор зависит от значений в перечислении. Некоторые перечисления имеют множество значений, поэтому им нужны все доступные биты:

  • NSInteger предлагает 2 ^ 31 положительных и отрицательных значений (по архитектуре 32 бит).
  • NSUInteger предлагает 2 ^ 32 положительных значения (по архитектуре с 32 битами).
  • Если вы перечисляете только положительные значения, используйте NSUInteger.
  • Если перечисление должно содержать как положительные, так и отрицательные значения, используйте NSInteger.
  • NSUInteger обычно используется для перечисления флага, поскольку он предоставляет 32 различных значения (по архитектуре 32 бит), которые будут объединены по желанию.

Я не знаю, есть ли правило выбора в команде разработчиков Apple для этого. Надеюсь, что так...

Ответ 3

Пока вы можете использовать что-то вроде

  typedef enum { constants... } sometype;

нет никакой гарантии о возможной битетизации типа данных. Ну, это не совсем верно, но это правда. Его лучше для API-интерфейсов определять в конкретных размерах данных, чем с чем-то, что может меняться в зависимости от используемых параметров компилятора.