Pourquoi ne pas déclarer NSInteger avec un *
-
06-07-2019 - |
Question
Je m'essaye au cours iPhone de Stanford sur iTunes U et je suis un peu confus en ce qui concerne les pointeurs. Dans la première mission, j'ai essayé de faire quelque chose comme ça
NSString *processName = [[NSProcessInfo processInfo] processName];
NSInteger *processID = [[NSProcessInfo processInfo] processIdentifier];
Ce qui a généré une erreur, après avoir scruté à l'aveuglette, j'ai découvert que c'était le * dans la ligne NSInteger qui était à l'origine du problème.
Donc, je ne comprends évidemment pas ce qui se passe. Je vais expliquer comment je pense que cela fonctionne et peut-être que quelqu'un aurait la gentillesse de signaler la faille.
Contrairement au développement Web, il me faut maintenant se soucier de la mémoire, eh bien, plus que dans le développement Web. Alors quand je créer une variable, on lui attribue un peu de mémoire quelque part (RAM I assumer). Au lieu de passer le variable autour, je passe un pointeur sur ce peu de mémoire autour. Et les pointeurs sont déclarés en préfixant le nom de variable avec *.
En supposant que j’ai raison, c’est pourquoi je n’ai pas besoin de le faire pour NSInteger?
La solution
NSInteger
est un type primitif, ce qui signifie qu'il peut être stocké localement sur la pile . Vous n'avez pas besoin d'utiliser un pointeur pour y accéder, mais vous pouvez le faire si vous le souhaitez. La ligne:
NSInteger *processID = [[NSProcessInfo processInfo] processIdentifier];
renvoie une variable réelle, pas son adresse. Pour résoudre ce problème, vous devez supprimer le *
:
NSInteger processID = [[NSProcessInfo processInfo] processIdentifier];
Vous pouvez avoir un pointeur sur un NSInteger
si vous en voulez vraiment un:
NSInteger *pointerToProcessID = &processID;
L'esperluette est l'adresse de l'opérateur. Il définit le pointeur sur NSInteger
égal à l'adresse de la variable en mémoire, plutôt qu'à l'entier de la variable.
Autres conseils
La raison pour laquelle vous ne déclarez pas NSInteger
avec un *
est parce que ce n'est pas un objet. Un NSInteger est simplement un int
ou un long
:
#if __LP64__
typedef long NSInteger;
#else
typedef int NSInteger;
endif
S'il est utilisé dans une application 32 bits, il s'agit d'un entier 32 bits et s'il est intégré dans une application 64 bits, il s'agit d'un entier 64 bits.
Bien sûr, vous pouvez passer un NSInteger
en tant que pointeur, mais la plupart des fonctions prennent simplement des arguments comme un NSInteger
et non un pointeur vers il.
Les objets, en revanche, ne peuvent être transmis à d'autres fonctions qu'en tant que pointeurs. En effet, la mémoire est allouée dynamiquement aux objets et ne peut donc pas être déclarée sur la pile. Dans la mesure où int
ou long
a une quantité fixe de mémoire allouée pour eux, ce n'est pas un problème.
Le *
signifie & # 8220; pointeur & # 8221 ;. La variable objet contient un pointeur sur un objet. Par conséquent, elle a un *
; la variable NSInteger contient un NSInteger et non un pointeur sur un NSInteger. Par conséquent, elle n'a pas de *
. Le fait de placer le *
sur cette variable vous donne au moins un avertissement car vous mettez un entier dans une variable de pointeur.
NSInteger est juste un typedef pour int, autant que je sache.
Utilisation des pointeurs
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