Por que eu não declarar NSInteger com um *
-
06-07-2019 - |
Pergunta
Eu estou tentando minha mão no campo de iPhone em Stanford no iTunes U e eu estou um pouco confuso sobre ponteiros. Na primeira tarefa, eu tentei fazer algo parecido com isto
NSString *processName = [[NSProcessInfo processInfo] processName];
NSInteger *processID = [[NSProcessInfo processInfo] processIdentifier];
O que gerou um erro, depois de tinkeing cegamente, eu descobri que ele era o * na linha NSInteger que estava causando o problema.
Então, eu obviamente não entendem o que está acontecendo. Vou explicar como eu acho que ele funciona e talvez alguém seria gentil o suficiente para apontar a falha.
Ao contrário de desenvolvimento web, agora eu preciso se preocupar com a memória, assim, mais do que no desenvolvimento web. Então, quando eu criar uma variável, ele é atribuído um pouco de um lugar de memória (RAM I presumir). Em vez de passar o em torno variável, que passam para um ponteiro aquele pedaço de volta memória. E ponteiros são declarados por prefixar o nome da variável com *.
Assumindo que estou certo, o que me intriga é por que eu não preciso fazer isso para NSInteger?
Solução
NSInteger
é um tipo primitivo, o que significa que podem ser armazenados localmente na pilha . Você não precisa usar um ponteiro para acessá-lo, mas você pode, se você quiser. A linha:
NSInteger *processID = [[NSProcessInfo processInfo] processIdentifier];
retorna uma variável real, não o seu endereço. Para corrigir isso, você precisa remover o *
:
NSInteger processID = [[NSProcessInfo processInfo] processIdentifier];
Você pode ter um ponteiro para um NSInteger
se você realmente quer um:
NSInteger *pointerToProcessID = &processID;
O e comercial é o endereço do operador. Ele define o ponteiro para o NSInteger
igual ao endereço da variável na memória, em vez de para o número inteiro na variável.
Outras dicas
A razão que você não declarar NSInteger
com um *
é porque ele não é um objeto. Um NSInteger é simplesmente uma int
ou um long
:
#if __LP64__
typedef long NSInteger;
#else
typedef int NSInteger;
endif
Se estiver a ser utilizado numa aplicação de 32 bits, que é um número inteiro de 32-bit, e se ele está a ser construído em um aplicativo de 64 bits, que é um número inteiro de 64-bit.
Claro, você pode passar um NSInteger
como um ponteiro, mas a maioria das funções simplesmente tomar argumentos como um NSInteger
e não um ponteiro para ele.
Objetos, por outro lado, só pode ser passado para outras funções como ponteiros. Isso ocorre porque os objetos têm memória alocada dinamicamente para eles, e por isso não pode ser declarada na pilha. Uma vez que um int
ou long
tem uma quantidade fixa de memória alocada para eles, isso não é um problema.
Os meios *
“ponteiro”. A variável de objecto mantém um apontador para um objecto, por isso, tem uma *
; a variável NSInteger detém uma NSInteger, não um ponteiro para um NSInteger, por isso não tem uma *
. Colocar o *
sobre essa variável dá-lhe, pelo menos, um aviso porque você está colocando um inteiro em uma variável ponteiro.
NSInteger é apenas um typedef para int, AFAIK.
Trabalho com ponteiros
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