Что делает CG_INLINE?

Я искал определения для таких вещей, как CGPoint для подсказок о том, как создавать свои собственные функции, но я не знаю цели CG_INLINE. Что происходит за кулисами здесь?

CG_INLINE CGPoint
CGPointMake(CGFloat x, CGFloat y)
{
  CGPoint p; p.x = x; p.y = y; return p;
}

CG_INLINE CGSize
CGSizeMake(CGFloat width, CGFloat height)
{
  CGSize size; size.width = width; size.height = height; return size;
}

Ответы

Ответ 1

Встроенные функции скомпилируются на сайт вызова, а не компилируются как один блок кода функции и инструкции вызова, выдаваемые при использовании функции. С осторожностью это обеспечивает немного большую скорость и большее количество обращений в кеш. Однако история inline в C и С++ является скалистой, поэтому этот макрос эффективно обеспечивает независимое от компилятора поведение static inline. Глядя на определение:

#if !defined(CG_INLINE)
# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
#  define CG_INLINE static inline
# elif defined(__MWERKS__) || defined(__cplusplus)
#  define CG_INLINE static inline
# elif defined(__GNUC__)
#  define CG_INLINE static __inline__
# else
#  define CG_INLINE static    
# endif
#endif /* !defined(CG_INLINE) */

Итак...

  • Для компиляторов, предоставляющих __STDC_VERSION__ соответствующей версии (в данном случае >= C99), это означает static inline (поскольку C99 допускает это изначально)
  • Аналогично для компиляторов Metrowerks Codewarrior или С++, которые поддерживают inline изначально.
  • Для GCC, не поддерживающих C99, он разрешает static __inline__. Использование __inline__ является спецификатором встроенного контура GCC для предыдущих стандартов C, где inline не поддерживается: http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Alternate-Keywords.html.
  • Если все это не удается, оно не беспокоит встроенный - это просто static.

Зачем беспокоиться обо всех этих определениях? Потому что Apple в своей истории прошла через несколько компиляторов. В дни ожидания компилятор Codewarrior C был инструментом выбора для пользователей. Начиная с OS X, Apple использует Objective C и С++ через (первоначально модификатор) GCC. В последнее время они переходят к clang. Этот макрос охватывает все случаи (и, учитывая, как новая Core Graphics, я подозреваю, это модифицированная версия более старого макроса).

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

Ответ 2

CG_INLINE - это макрос, который используется для обозначения метода как встроенной функции. Точный синтаксис (зависит?) Зависит от компилятора, а через препроцессорные проверки правильный для вашего компилятора выбран.

Для текущих GCC он должен быть static inline.

Точкой функции, помеченной inline, является то, что компилятор может вставить эквивалент этого тела функции, где была вызвана функция, вместо того, чтобы делать (чуть более дорогостоящий) вызов функции. Поэтому, если у вас есть:

inline int foo(int a, int b)
{
   return a + b;
}

void bar(int a, int b)
{
   NSLog(@"%d", foo(a, b));
}

Затем компилятору разрешено внутренне преобразовывать его в:

void bar(int a, int b)
{
   NSLog(@"%d", a + b);
}

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

Обратите внимание, что это означает, что компилятор может сделать это преобразование, это не обязательно означает, что он это делает. Зависит от настроек компилятора.

Ответ 3

CG_INLINE - это #define для static inline. Это заставляет компилятор создавать код для функции inline, а не создавать вызов функции в стеке. Подробнее см. здесь и здесь.