Почему я не объявляю NSInteger с *
Я пробовал свою руку на курсе iPhone из Стэнфорда на iTunes U, и я немного запутался в указателях. В первом задании я попытался сделать что-то вроде этого
NSString *processName = [[NSProcessInfo processInfo] processName];
NSInteger *processID = [[NSProcessInfo processInfo] processIdentifier];
Сгенерировав ошибку, после слепого слепого, я обнаружил, что именно в строке NSInteger возникла проблема.
Поэтому я, очевидно, не понимаю, что происходит. Я объясню, как я думаю, что это работает, и, возможно, кто-то будет достаточно любезен, чтобы указать на недостаток.
В отличие от веб-разработки, мне теперь нужно беспокоиться о памяти, ну, более того, чем в веб-разработке. Поэтому, когда я создать переменную, она получает выделение бит памяти (RAM я предполагать). Вместо того, чтобы переменная вокруг, я передаю указатель на этот бит памяти вокруг. А также указатели объявляются путем префикса имя переменной с помощью *.
Предполагая, что я прав, что меня озадачивает, почему мне не нужно это делать для NSInteger?
Ответы
Ответ 1
NSInteger
является примитивным типом, что означает, что он может храниться локально в стеке. Вам не нужно использовать указатель для доступа к нему, но вы можете, если хотите. Строка:
NSInteger *processID = [[NSProcessInfo processInfo] processIdentifier];
возвращает действительную переменную, а не ее адрес. Чтобы исправить это, вам нужно удалить *
:
NSInteger processID = [[NSProcessInfo processInfo] processIdentifier];
У вас может быть указатель на NSInteger
, если вы действительно этого хотите:
NSInteger *pointerToProcessID = &processID;
Амперсанд - это адрес оператора. Он устанавливает указатель на NSInteger
, равный адресу переменной в памяти, а не целому числу в переменной.
Ответ 2
Причина, по которой вы не объявляете NSInteger
с *
, состоит в том, что это не объект. NSInteger - это просто int
или long
:
#if __LP64__
typedef long NSInteger;
#else
typedef int NSInteger;
endif
Если он используется в 32-битном приложении, он представляет собой 32-разрядное целое число, и если он встроен в 64-разрядное приложение, это 64-разрядное целое.
Конечно, вы можете передать NSInteger
как указатель, но большинство функций просто принимают аргументы как NSInteger
, а не указатель на него.
С другой стороны, объекты могут передаваться только другим функциям в качестве указателей. Это связано с тем, что объекты имеют динамическую память для них и поэтому не могут быть объявлены в стеке. Поскольку int
или long
имеет фиксированный объем памяти, выделенный для них, это не проблема.
Ответ 3
*
означает "указатель". Переменная объекта содержит указатель на объект, поэтому он имеет *
; переменная NSInteger содержит NSInteger, а не указатель на NSInteger, поэтому он не имеет *
. Помещение *
на эту переменную дает вам хотя бы предупреждение, потому что вы помещаете целое число в переменную-указатель.
Ответ 4
NSInteger - это просто typedef для int, AFAIK.
Ответ 5
Работа с указателями
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