Perché non dichiaro NSInteger con un *
-
06-07-2019 - |
Domanda
Sto provando la mia mano al corso iPhone di Stanford su iTunes U e sono un po 'confuso riguardo ai puntatori. Nel primo incarico, ho provato a fare qualcosa del genere
NSString *processName = [[NSProcessInfo processInfo] processName];
NSInteger *processID = [[NSProcessInfo processInfo] processIdentifier];
Il che ha generato un errore, dopo averlo girato alla cieca, ho scoperto che era il * nella riga NSInteger a causare il problema.
Quindi ovviamente non capisco cosa sta succedendo. Spiegherò come penso che funzioni e forse qualcuno sarebbe abbastanza gentile da evidenziare il difetto.
A differenza dello sviluppo web, ora ho bisogno preoccuparsi della memoria, beh, più che nello sviluppo web. Quindi quando io creare una variabile, viene assegnato a un po 'di memoria da qualche parte (RAM I assumere). Invece di passare il variabile intorno, passo un puntatore a quel po 'di memoria in giro. E i puntatori vengono dichiarati con il prefisso nome della variabile con *.
Supponendo che abbia ragione, ciò che mi confonde è perché non devo farlo per NSInteger?
Soluzione
NSInteger
è un tipo primitivo, il che significa che può essere archiviato localmente nello stack . Non è necessario utilizzare un puntatore per accedervi, ma è possibile se si desidera. La linea:
NSInteger *processID = [[NSProcessInfo processInfo] processIdentifier];
restituisce una variabile effettiva, non il suo indirizzo. Per risolvere questo problema, devi rimuovere *
:
NSInteger processID = [[NSProcessInfo processInfo] processIdentifier];
Puoi avere un puntatore a un NSInteger
se ne vuoi davvero uno:
NSInteger *pointerToProcessID = &processID;
La e commerciale è l'indirizzo dell'operatore. Imposta il puntatore su NSInteger
uguale all'indirizzo della variabile in memoria, anziché all'intero nella variabile.
Altri suggerimenti
Il motivo per cui non si dichiara NSInteger
con un *
è perché non è un oggetto. Un NSInteger è semplicemente un int
o un long
:
#if __LP64__
typedef long NSInteger;
#else
typedef int NSInteger;
endif
Se viene utilizzato in un'applicazione a 32 bit, è un numero intero a 32 bit e se viene creato in un'applicazione a 64 bit, è un numero intero a 64 bit.
Naturalmente, puoi passare un NSInteger
come puntatore, ma la maggior parte delle funzioni accetta semplicemente argomenti come NSInteger
e non un puntatore a esso.
Gli oggetti, d'altra parte, possono essere passati ad altre funzioni solo come puntatori. Questo perché gli oggetti hanno memoria allocata dinamicamente per loro, e quindi non possono essere dichiarati nello stack. Poiché un int
o long
ha una quantità fissa di memoria allocata per loro, questo non è un problema.
*
significa "puntatore". La variabile oggetto contiene un puntatore a un oggetto, quindi ha un *
; la variabile NSInteger contiene un NSInteger, non un puntatore a un NSInteger, quindi non ha un *
. Mettere *
su quella variabile ti dà almeno un avvertimento perché stai mettendo un numero intero in una variabile puntatore.
NSInteger è solo un typedef per int, AFAIK.
Lavorare con i puntatori
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