В чем разница между *(id *)((char *)object + ivar_getOffset(ivar)) и object_getIvar(object, ivar)

Согласно Справочник по среде выполнения Objective-C:

ivar_getOffset Возвращает смещение переменной экземпляра.

ptrdiff_t ivar_getOffset(Ivar ivar) Обсуждение Для переменных экземпляра типа id или других типов объектов вызовите object_getIvar и object_setIvar вместо использования этого смещения для прямого доступа к данным переменной экземпляра.

Объявлено в runtime.h

Почему это? Что делает object_getIvar с типами объектов?

РЕДАКТИРОВАТЬ: вопрос изменен с подписки (void *) на (id *).


person Jared Pochtar    schedule 26.08.2010    source источник
comment
Подписка void должна вызвать жалобу компилятора.   -  person dreamlax    schedule 26.08.2010


Ответы (2)


Нет никакой разницы между этими двумя подходами, когда дело доходит до получения значения ивара. Вы можете убедиться в этом, посмотрев на реализацию object_getIvar() в открытом исходном коде Apple Код времени выполнения Obj-C.

object_setIvar() делает больше, чем просто назначает смещение от указателя объекта. Осторожно вызовите функцию среды выполнения сборки мусора objc_assign_ivar() для выполнения фактического назначения.

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

person Jeremy W. Sherman    schedule 25.09.2010

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

Обратите внимание, что вы не можете надежно увеличивать значение void *, основываясь на следующей информации из стандарта C99 (выделено мной):

C99 §6.2.5 (1): (...) Типы подразделяются на типы объектов (типы, которые полностью описывают объекты), типы функций (типы, которые описывают функции) и неполные типы (типы, которые описывают объекты, но не содержат информации, необходимой для определения их размеров).

C99 §6.2.5 (19): Тип void содержит пустой набор значений; это неполный тип, который не может быть завершен.

C99 §6.5.6 (2): Кроме того, либо оба операнда должны иметь арифметический тип, либо один операнд должен быть указателем на тип объекта, а другой должен иметь целочисленный тип. (Увеличение эквивалентно добавлению 1.)

C99 §6.5.2.1 (1): Одно из выражений должно иметь тип «указатель на тип объекта», другое выражение должно иметь целочисленный тип, а результат должен иметь тип «тип».

Чтобы увеличить указатель на произвольное число, вы можете вместо этого использовать char *.

person dreamlax    schedule 26.08.2010