2010-02-11 18 views
12

Je me demandais quelle était la logique des différents styles de déclaration enum sur le cacao?Pourquoi le cacao n'utilise-t-il pas le même style de déclaration enum partout?

Comme ceci:

enum { constants.. }; typedef NSUInteger sometype; 

est la raison d'utiliser typedef pour obtenir assigments à NSUInteger travailler sans jeter?

Parfois, le typedef est l'une des NSInteger/NSUInteger, pourquoi ne pas utiliser NSInteger toujours? Y a-t-il un réel avantage à utiliser NSUInteger?

tagnames Enum sont encore utilisés parfois, comme here sur _NSByteOrder.

Cette réponse a été très utile aussi: What is a typedef enum in Objective-C?.

+1

typedef et enum sont très différents ... Je ne comprends pas vraiment votre question? Les enum sont utilisés pour configurer des collections de constantes entières nommées. typedef sont utilisés pour donner un nouveau nom à un type de données, souvent pour prendre en charge différentes architectures ... – t00ny

Répondre

1

Alors que vous pouvez utiliser quelque chose comme

typedef enum { constants... } sometype; 

il n'y a aucune garantie quant à l'éventuelle bitsize du type de données. Eh bien, ce n'est pas strictement vrai, mais c'est assez vrai. Il est préférable que les API soient définies dans des tailles de données concrètes plutôt qu'avec quelque chose qui peut changer en fonction des paramètres du compilateur utilisés.

2

La raison d'utiliser typedef pour obtenir assigments à NSUInteger travailler sans jeter?

Le typedef est utilisé pour spécifier le type de base pour les valeurs d'énumération. Vous pouvez toujours convertir une valeur d'énumération en un autre type à condition de tronquer la valeur, en la transposant à un type plus petit (NSUInteger à unsigned short).

et ont été introduites pour faciliter la migration 64 bits des applications, en fournissant un type indépendant d'architecture/de plate-forme pour les entiers signés et non signés. De cette façon, quel que soit le nombre de bits du processeur, les applications n'ont pas besoin d'être réécrites.

Parfois, le typedef est l'une des NSInteger/NSUInteger, pourquoi ne pas utiliser NSInteger toujours? Est-il réel bénéficier de NSUInteger?

Le choix dépend des valeurs de l'énumération. Certaines énumérations ont beaucoup de valeurs, elles ont donc besoin de tous les bits disponibles:

  • NSInteger offre 2^31 valeurs positives et négatives (sur l'architecture 32 bits).
  • NSUInteger offre 2^32 valeurs positives (sur architecture 32 bits).
  • Si l'énumération ne contient que des valeurs positives, utilisez NSUInteger.
  • Si l'énumération est destinée à contenir des valeurs positives et négatives, utilisez NSInteger.
  • NSUInteger est généralement utilisé pour l'énumération des indicateurs, car il fournit 32 valeurs distinctes (sur l'architecture 32 bits) à combiner à volonté.

Je ne sais pas s'il existe une règle de choix dans l'équipe de développement d'Apple pour cela. Je l'espère ...

+0

Vous voulez dire * 2 à la puissance de * 31 et 32, n'est-ce pas? En outre, les deux types offrent 2 ** 32 valeurs distinctes; la différence est qu'avec un type signé (comme 'NSInteger'), la moitié d'entre eux (2 ** 31) sont négatifs, et environ la moitié (2 ** 31 - 1) sont positifs. Avec un type non signé, tous les 2 ** 32 sont non négatifs. Et c'est la vraie différence: si toutes vos valeurs d'énumération, jamais, vont être positives, vous pouvez déclarer le type comme «NSUInteger». Inversement, si vous avez des valeurs négatives, vous devez utiliser 'NSInteger'. –

+0

Vous avez raison. Je voulais dire des valeurs de drapeau. J'ai mis à jour ma réponse en conséquence. –

12

Plusieurs raisons:

Raison 1: Flexibilité:

enum lickahoctor { yes = 0, no = 1, maybe = 2 }; 

déclare une énumération. Vous pouvez utiliser les valeurs yes, no et maybe n'importe où et les affecter à n'importe quel type intégral. Vous pouvez également l'utiliser comme un type, en écrivant

enum lickahoctor myVar = yes; 

Cela rend agréable parce que si une fonction prend un paramètre avec le ENUM de type lickahoctor vous saurez que vous pouvez affecter yes, no ou maybe à elle. En outre, le débogueur le saura, il affichera donc le nom symbolique au lieu de la valeur numérique. Le problème est, le compilateur vous permettra seulement d'assigner les valeurs que vous avez définies dans enum lickahoctor à myVar. Si vous voulez par exemple définir quelques drapeaux dans la classe de base, ajoutez quelques drapeaux supplémentaires dans la sous-classe, vous ne pouvez pas le faire de cette façon.

Si vous utilisez un int à la place, vous n'avez pas ce problème. Donc vous voulez utiliser une sorte d'int, donc vous pouvez assigner des constantes arbitraires.

Raison n ° 2: la compatibilité binaire:

Le compilateur choisit une belle taille qui correspond à toutes les constantes que vous avez défini dans un ENUM. Il n'y a aucune garantie que vous obtiendrez. Donc, si vous écrivez une structure contenant une telle variable directement dans un fichier, il n'y a aucune garantie qu'elle sera toujours de la même taille lorsque vous la relirez avec la prochaine version de votre application (selon la norme C, au moins - - Ce n'est pas si sombre en pratique.

Si vous utilisez une sorte d'int à la place, la plate-forme garantit généralement une taille particulière pour ce nombre. Surtout si vous utilisez un des types garantis à une taille particulière, comme int32_t/uint32_t.

Raison n ° 3: Lisibilité et auto-documentation

Lorsque vous déclarez maVar ci-dessus, il est immédiatement évident que les valeurs que vous pouvez mettre. Si vous utilisez simplement un int, ou un uint32_t, ce n'est pas le cas. Alors qu'est-ce que vous faites est que vous utilisez

enum { yes, no, maybe }; 
typedef uint32_t lickahoctor; 

pour définir un joli nom pour l'entier quelque part près des constantes qui rappelleront les gens qu'une variable de ce type peut contenir cette valeur. Mais vous bénéficiez toujours d'une taille fixe prévisible et de la possibilité de définir des valeurs supplémentaires dans les sous-classes, si nécessaire.

Raison 4: Soutien à bitfields

variables enum typé ne supportent que assignant exactement une valeur de leurs options. Donc, si vous essayez d'implémenter un champ de bits, vous ne pouvez pas le taper comme un champ de bits. En outre, vous devez utiliser des variables non signées pour éviter que l'extension de signe ne vous vienne.

+0

NSInteger n'est pas garanti d'être une taille particulière, il est garanti d'être différent sur 'i386' et' x86_64'. Si vous avez écrit un fichier binaire avec un 'lickahoctor' sur un Core Duo, mis à jour votre Mac et le relire, l'hilarité s'ensuivrait. –

+0

Bien sûr, Graham. Brainfart là. Merci d'avoir corrigé cela. – uliwitness

+2

+1 pour 'lickahoctor', même si c'est une blague à l'intérieur. – Abizern