2010-02-11 5 views
12

Mi stavo chiedendo quale sia la logica dietro i diversi stili di dichiarazione enum sul cacao?Perché il cacao non usa lo stesso stile di dichiarazione enum ovunque?

Ti piace questa:

enum { constants.. }; typedef NSUInteger sometype; 

è la ragione per usare typedef per arrivare a assigments NSUInteger a lavorare senza la fusione?

A volte il typedef è uno di NSInteger/NSUInteger, perché non utilizzare sempre NSInteger? C'è un reale vantaggio nell'uso di NSUInteger?

I nomi di enumerazione vengono ancora utilizzati a volte, ad esempio here in _NSByteOrder.

Anche questa risposta è stata molto utile: What is a typedef enum in Objective-C?.

+1

typedef e enum sono molto diversi ... Non capisco davvero la tua domanda? enumerazioni vengono utilizzate per impostare raccolte di costanti di numeri interi con nome. typedef sono usati per dare un tipo di dati un nuovo nome, spesso per supportare architetture diverse ... – t00ny

risposta

1

Mentre si potrebbe usare qualcosa come

typedef enum { constants... } sometype; 

non v'è alcuna garanzia circa l'eventuale Bitsize del tipo di dati. Beh, questo non è assolutamente vero, ma è abbastanza vero. È meglio per le API essere definite in dimensioni di dati concrete, piuttosto che con qualcosa che può cambiare a seconda delle impostazioni del compilatore utilizzate.

2

è il motivo per usare typedef per arrivare assigments a NSUInteger a lavorare senza fusione?

Il typedef viene utilizzato per specificare il tipo di base per i valori di enumerazione. È sempre possibile trasmettere un valore di enumerazione a un altro tipo purché il valore venga troncato, convertendolo in un tipo più piccolo (NSUInteger in unsigned short).

NSInteger e NSUInteger sono stati introdotti per facilitare la migrazione di 64 bit di applicazioni, fornendo un tipo indipendente da architettura/piattaforma per interi sia con segno che senza segno. In questo modo, indipendentemente dal numero di bit della CPU, le applicazioni non devono essere riscritte.

A volte il typedef è uno dei NSInteger/NSUInteger, perché non utilizzare NSInteger sempre? C'è un vero vantaggio usando NSUInteger?

La scelta dipende dai valori nell'enumerazione. Alcune enumerazioni hanno molti valori, quindi hanno bisogno di tutti i bit disponibili:

  • NSInteger offre 2^31 valori positivi e negativi (su architettura a 32 bit).
  • NSUInteger offre 2^32 valori positivi (su architettura a 32 bit).
  • Se l'enumerazione è intesa per contenere solo valori positivi, utilizzare NSUInteger.
  • Se l'enumerazione è destinata a contenere valori sia positivi sia negativi, utilizzare NSInteger.
  • NSUInteger viene in genere utilizzato per l'enumerazione flag, in quanto fornisce 32 valori distinti (su architettura a 32 bit) da combinare a piacere.

Non so se esiste una regola di scelta per il team di sviluppo Apple. Lo spero ...

+0

Vuoi dire * 2 alla potenza di * 31 e 32, giusto? Inoltre, entrambi i tipi offrono 2 ** 32 valori distinti; la differenza è che con un tipo firmato (come 'NSInteger'), la metà di essi (2 ** 31) è negativo e circa la metà (2 ** 31 - 1) è positivo. Con un tipo senza segno, tutti i 2 ** 32 sono non negativi. E questa è la vera differenza: se tutti i valori di enumerazione, in assoluto, saranno positivi, è possibile dichiarare il tipo "NSUInteger". Al contrario, se si hanno valori negativi, è necessario utilizzare 'NSInteger'. –

+0

Hai ragione. Stavo a significare valori di bandiera. Ho aggiornato la mia risposta di conseguenza. –

12

diversi motivi:

Motivo 1: Flessibilità:

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

dichiara un'enumerazione. È possibile utilizzare i valori yes, no e maybe ovunque e assegnarli a qualsiasi tipo integrale. È inoltre possibile utilizzare questo come un tipo, scrivendo

enum lickahoctor myVar = yes; 

In questo modo è bello perché se una funzione accetta un parametro con il tipo enum lickahoctor saprete che è possibile assegnare yes, no o maybe ad esso. Inoltre, il debugger saprà, quindi mostrerà il nome simbolico invece del valore numerico. Il problema è che il compilatore ti consente di assegnare solo i valori che hai definito in enum lickahoctor a myVar. Se per esempio vuoi definire alcuni flag nella classe base, quindi aggiungi altri flag nella sottoclasse, non puoi farlo in questo modo.

Se si utilizza invece un int, non si ha questo problema. Quindi vuoi usare una sorta di int, quindi puoi assegnare costanti arbitrarie.

Motivo 2: compatibilità binaria:

Il compilatore sceglie una bella dimensione che si adatta a tutte le costanti che avete definito in un enum. Non c'è alcuna garanzia di ciò che otterrai. Quindi se scrivi una struct contenente tale variabile direttamente in un file, non c'è alcuna garanzia che rimarrà della stessa dimensione quando la rileggi con la versione successiva della tua app (secondo lo standard C, almeno - - non è proprio così cupo nella pratica).

Se si utilizza un tipo di int invece, la piattaforma di solito garantisce una dimensione particolare per quel numero. Soprattutto se si utilizza uno dei tipi garantiti per una dimensione particolare, ad esempio int32_t/uint32_t.

Motivo 3: Leggibilità e di auto-documentazione

Quando si dichiara myVar sopra, è immediatamente evidente quali valori si può mettere in esso. Se usi semplicemente un int, o un uint32_t, non lo è. Quindi, ciò che si fa è di utilizzare

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

per definire un bel nome per il numero intero da qualche parte vicino le costanti che ricordano le persone che una variabile di questo tipo può contenere questo valore. Tuttavia, si ottiene comunque il vantaggio di una dimensione fissa prevedibile e la possibilità di definire valori aggiuntivi in ​​sottoclassi, se necessario.

Motivo 4: Supporto per campi di bit

variabili enum tipizzato solo supporto assegnando esattamente un valore dai loro opzioni. Quindi, se stai cercando di implementare un campo bit, non puoi inserirlo come bitfield. Inoltre, è necessario utilizzare variabili non firmate per evitare che l'estensione del segno ti rovini.

+0

NSInteger non è garantito per una dimensione particolare, è garantito che sia diverso su 'i386' e' x86_64'. Se hai scritto un file binario con un 'lickahoctor' su un Core Duo, aggiornato il tuo Mac e rileggendolo di nuovo, l'ilarità potrebbe derivarne. –

+0

Ovviamente, Graham. Brainfart lì. Grazie per averlo corretto. – uliwitness

+2

+1 per 'lickahoctor', anche se è uno scherzo interno. – Abizern