web-dev-qa-db-fra.com

Pourquoi ne déclare-t-on pas NSInteger avec un *

J'essaie le cours iPhone de Stanford sur iTunes U et je suis un peu confus au sujet des 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 bricolé aveuglément, j'ai découvert que c'était le * dans la ligne NSInteger qui causait le problème.

Je ne comprends donc é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, j'ai maintenant besoin de me soucier de la mémoire, bien plus que du développement Web. Donc, quand je crée une variable, elle reçoit un peu de mémoire quelque part (RAM je suppose). Au lieu de passer la variable, je passe un pointeur sur ce morceau de mémoire. Et les pointeurs sont déclarés en préfixant le nom de la variable avec *.

En supposant que j'ai raison, ce qui me laisse perplexe, c'est pourquoi je n'ai pas besoin de faire cela pour NSInteger?

42
gargantuan

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 vers 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 dans la variable.

70
Dan Lorenc

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, c'est un entier 32 bits, et s'il est construit dans une application 64 bits, c'est un entier 64 bits.

Bien sûr, vous pouvez passez un NSInteger en tant que pointeur, mais la plupart des fonctions prennent simplement des arguments en tant que NSInteger et non un pointeur.

Les objets, en revanche, ne peuvent être transmis à d'autres fonctions que comme pointeurs. En effet, la mémoire des objets leur est allouée dynamiquement et ne peut donc pas être déclarée sur la pile. Étant donné qu'un int ou long a une quantité fixe de mémoire allouée pour eux, ce n'est pas un problème.

25
Alex Rozanski

Le * signifie "pointeur". La variable objet contient un pointeur sur un objet, il a donc un *; la variable NSInteger contient un NSInteger, pas un pointeur vers un NSInteger, donc il n'a pas de *. Mettre le * sur cette variable vous donne au moins un avertissement car vous mettez un entier dans une variable de pointeur.

3
Peter Hosey

NSInteger n'est qu'un typedef pour int, AFAIK.

2
Andrei Tanasescu

Travailler avec 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
0
yoAlex5