Почему какао не использует тот же перечислимый стиль объявления везде?

Я задавался вопросом, каково объяснение позади различных стилей перечислимого объявления по какао?

Как это:

enum { constants.. }; typedef NSUInteger sometype;

Причина состоит в том, чтобы использовать определение типа, чтобы заставить присвоения на NSUInteger работать без кастинга?

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

Перечисление tagnames все еще иногда используется, как здесь на _NSByteOrder.

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

12
задан Community 23 May 2017 в 10:29
поделиться

3 ответа

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

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

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

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

enum lickahoctor myVar = yes;

. Это удобно, потому что если функция принимает параметр с типом enum lickahoctor, вы будете знать, что можете назначить yes , no или , возможно, к нему. Кроме того, отладчик будет знать, поэтому он будет отображать символическое имя вместо числового значения. Проблема в том, что компилятор позволит вам присвоить значения, которые вы определили в 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: Поддержка битовых полей.

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

12
ответ дан 2 December 2019 в 20:40
поделиться

Является ли причина использования 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 правило выбора для этого. Надеюсь, что так ...

2
ответ дан 2 December 2019 в 20:40
поделиться

Boost не является большой библиотекой.

Это коллекция множества небольших библиотек. Большинство из них такие маленькие, что они содержатся в заголовке или два. Использование boost:: noncopyable не перетаскивает boost:: regex или boost:: thread в код. Это разные библиотеки. Они распространяются как часть той же библиотеки. Но вы платите только за те, что используете.

Но говоря в целом, потому что большие библиотеки существуют, даже если Boost не является одной из них:

Есть ли основания для моего мышления, или я просто неразумен и/или невежественен? Даже если я использую только одну или две функции большой библиотеки, связываясь с этой библиотекой, я понесу накладные расходы во время выполнения?

Нет основы, больше или меньше . Вы можете проверить это самостоятельно.

Запишите небольшую программу C++ и скомпилируйте ее. Теперь добавьте к нему новую функцию, которая никогда не вызывается, но определена. Скомпилировать программу еще раз. Если оптимизация включена, она удаляется компоновщиком, поскольку не используется. Таким образом, стоимость включения дополнительного неиспользуемого кода равна нулю.

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

Еще одно исключение состоит в том, что при динамической связи с .dll или .so вся библиотека должна быть распределена и поэтому ее нельзя удалить из неиспользуемого кода. Но библиотеки, которые статически компилируются в исполняемый файл (либо как статические библиотеки (.lib или .a), либо как включенные заголовочные файлы, обычно могут быть обрезаны компоновщиком, удаляя неиспользуемые символы.

-121--110â9-

Можно использовать mod _ auth _ tkt . auth _ tkt - это подписанный файл cookie с идентификатором пользователя, понятным для Apache. Веб-приложение должно установить файл cookie при входе и выходе пользователя. Apache может вывести REMOTE _ USER из файла cookie, передать его в ваше веб-приложение или веб- приложение не Django, работающий на том же сервере, включить его в журналы, что угодно.

-121--3375261-

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

  typedef enum { constants... } sometype;

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

1
ответ дан 2 December 2019 в 20:40
поделиться