Почему бы мне не объявить NSInteger с *
-
06-07-2019 - |
Вопрос
Я пробую свои силы на курсе iPhone из Стэнфорда на iTunes U, и меня немного смущают указатели. В первом задании я пытался сделать что-то вроде этого
NSString *processName = [[NSProcessInfo processInfo] processName];
NSInteger *processID = [[NSProcessInfo processInfo] processIdentifier];
В результате возникла ошибка, после вслепую я обнаружил, что именно * в строке NSInteger и была причиной проблемы. Р>
Так что я явно не понимаю, что происходит. Я объясню, как я думаю, что это работает, и, возможно, кто-то будет достаточно любезен, чтобы указать на недостаток. Р>
В отличие от веб-разработки, мне сейчас нужно беспокоиться о памяти, ну, в большей степени, чем в веб-разработке. Итак, когда я создать переменную, она получает немного памяти где-то (RAM я предполагать). Вместо прохождения переменная вокруг, я передаю указатель на этот кусок памяти вокруг. А также указатели объявляются с префиксом имя переменной с *.
Предполагая, что я прав, меня озадачивает, почему мне не нужно делать это для NSInteger?
Решение
NSInteger
- это примитивный тип, что означает, что он может храниться локально в стеке . Вам не нужно использовать указатель для доступа к нему, но вы можете, если хотите. Строка:
NSInteger *processID = [[NSProcessInfo processInfo] processIdentifier];
возвращает фактическую переменную, а не ее адрес. Чтобы это исправить, вам нужно удалить *
:
NSInteger processID = [[NSProcessInfo processInfo] processIdentifier];
У вас может быть указатель на NSInteger
, если он действительно нужен:
NSInteger *pointerToProcessID = &processID;
Амперсанд - это адрес оператора. Он устанавливает указатель на NSInteger
, равный адресу переменной в памяти, а не целому числу в переменной.
Другие советы
Причина, по которой вы не объявляете NSInteger
с *
, заключается в том, что это не объект. NSInteger - это просто int
или long
:
#if __LP64__
typedef long NSInteger;
#else
typedef int NSInteger;
endif
Если он используется в 32-разрядном приложении, это 32-разрядное целое число, а если оно встроено в 64-разрядное приложение, это 64-разрядное целое число.
Конечно, вы можете передать NSInteger
в качестве указателя, но большинство функций просто принимают аргументы как NSInteger
, а не как указатель на Это. Р>
Объекты, с другой стороны, могут быть переданы другим функциям только в качестве указателей. Это связано с тем, что для объектов динамически выделяется память, и поэтому они не могут быть объявлены в стеке. Поскольку для int
или long
для них выделено фиксированное количество памяти, это не проблема.
*
означает & # 8220; указатель & # 8221 ;. Переменная объекта содержит указатель на объект, поэтому она имеет *
; переменная NSInteger содержит NSInteger, а не указатель на NSInteger, поэтому она не имеет *
. Помещение *
в эту переменную дает вам как минимум предупреждение, потому что вы помещаете целое число в переменную-указатель.
NSInteger - просто определение типа для int, AFAIK.
Работа с указателями
NSInteger integer1 = 1;
NSLog(@"1. integer1:%ld &integer1:%p", integer1, &integer1);
//1. integer1:1 &integer1:0x7ffee59e8a98
NSInteger *integer2 = &integer1;
NSLog(@"2. integer2:%p &integer2:%p *integer2:%ld", integer2, &integer2, *integer2);
//2. integer2:0x7ffee59e8a98 &integer2:0x7ffee59e8a90 *integer2:1
*integer2 = 2;
NSLog(@"3. integer2:%p &integer2:%p *integer2:%ld \t integer1:%ld &integer1:%p", integer2, &integer2, *integer2, integer1, &integer1);
//3. integer2:0x7ffee59e8a98 &integer2:0x7ffee59e8a90 *integer2:2 integer1:2 &integer1:0x7ffee59e8a98