2009-09-16 13 views
44

So che è piuttosto idiomatico, o almeno di stile, in C per dichiarare costanti numeriche come enum s invece di #define.Come si dichiarano le costanti di stringa in C?

/* bad style */ 
#define MAXLINE 1024 

/* good/better style */ 
enum { 
    MAX_LINE = 1024 
}; 

Esiste una regola equivalente per la definizione delle costanti di stringa?

/* is this good style? */ 
#define HELLO "Hello World" 

/* or is this better? */ 
const char *HELLO2 = "Howdy"; 

Cosa preferisci? Se possibile, mostra alcuni inconvenienti di entrambi i metodi.

risposta

70

C'è un altro (almeno) via di Roma:

static const char HELLO3[] = "Howdy"; 

(static - opzionale - è quello di evitare che in conflitto con altri file). Preferirei questo su const char*, perché in tal caso sarà possibile utilizzare sizeof(HELLO3) e quindi non è necessario posticipare fino al runtime cosa è possibile fare in fase di compilazione.

La definizione ha un vantaggio di concatenazione in fase di compilazione, tuttavia (si consideri HELLO ", World!") e si può anche sizeof(HELLO).

Ma poi puoi anche preferire const char* e usarlo su più file, il che ti farebbe risparmiare un pizzico di memoria.

In breve, dipende.

+0

Grazie per la spiegazione. La ragione per usare 'enum's invece di macro constanti o' const int' per valori interi costanti è il fatto che questo è l'unico modo sicuro per dichiarare un numero intero costante che può essere usato come un limite di array. Beh ... La concatenazione della stringa del tempo di compilazione mi ha quasi convinto a usare '# define's per le stringhe, ma mi limiterò a' const char * 'per la sicurezza del tipo usando' static' dove applicabile. In breve userò 'enum' per le costanti intere e le variabili' const' per tutto il resto. –

+1

tatt, suggerirei che non si attacchi a nulla. * Non tutte le costanti sono uguali *. Se non hai intenzione di concatenare, non hai bisogno di #define, se non hai nemmeno bisogno delle dimensioni, non ti interessa affatto. Quello che non riesco a vedere è come 'const char *' è meglio di 'const char []' * dove static è applicabile *. Ma poi di nuovo, se non hai bisogno delle dimensioni, non è neanche peggio ;-) Gli array –

9

Un vantaggio (anche se molto piccola) di definire stringa costanti è che è possibile concatenare loro:

 
#define HELLO "hello" 
#define WORLD "world" 

puts(HELLO WORLD); 

Non sono sicuro che sia davvero un vantaggio, ma è una tecnica che non può essere utilizzato con const char *'S.

3

Lo svantaggio principale del metodo #define è che la stringa viene duplicata ogni volta che viene utilizzata, quindi è possibile finire con un sacco di copie nell'eseguibile, rendendola più grande.

+5

Credo che il compilatore li ottimizzerà almeno finché saranno utilizzati nello stesso file. Quindi non è davvero "ogni volta che viene utilizzato", ma sì, la definizione della costante globale fa risparmiare spazio a volte. –

+2

è vero, a meno che il compilatore o il linker non comprima le copie in una sola. Questa funzionalità è talvolta chiamata anche "pooling di stringhe" – Rom

-2

Per il primo. Gli enumerati sono per default numeri interi, il che significa che puoi passare quel valore solo a qualcosa che accetta solo numeri interi.

Il secondo mi piace di più: const char * versione invece di #define. Il motivo è che gli array in c sono puntatori, il che significa che ogni volta che si desidera utilizzare la versione #define, è necessario creare un'istanza di questa stringa solo per utilizzarla.

+1

non sono puntatori e non c'è alcun concetto di "istanza di stringa" quando si tratta di costante di stringa. E se gli array fossero dei puntatori che non significherebbe che la stringa debba essere istanziata anche se esistesse una cosa del genere ;-) –

+0

stava parlando di costanti numeriche. Gli array vengono passati di solito come riferimenti Almeno non riesco a capire altro modo per farlo. così. Qual è il rendimento predefinito in questo caso? { const char * str1 = HELLO; const char * str1 = HELLO; return (str1 == str2); } –

+0

Il valore di ritorno dipende dall'implementazione, ma (supponendo che intendessi str2 nel secondo compito) la maggior parte delle implementazioni restituisce true - prova, entrambi i puntatori faranno riferimento alla stessa stringa nel segmento di dati costante. Ma questo codice non ha nulla a che fare con gli array, è un semplice puntatore. Per quanto riguarda il passaggio degli array come puntatore, ciò non implica che gli array * siano * puntatori. 'int *' e 'int [2]' sono tipi diversi. E non solo teoricamente - non puoi sensibilmente 'sizeof()' puntatore, non puoi incrementare l'array, ecc. –

7

Se volete un "const string", come la tua domanda dice, vorrei davvero andare per la versione lei ha dichiarato nella sua domanda:

/* first version */ 
const char *HELLO2 = "Howdy"; 

In particolare, vorrei evitare:

/* second version */ 
const char HELLO2[] = "Howdy"; 

Motivo: il problema con la seconda versione è che il compilatore farà una copia dell'intera stringa "Howdy", PLUS quella stringa è modificabile (quindi non proprio const).

D'altra parte, la prima versione è una stringa const accessibile dal puntatore const HELLO2 e non c'è modo che qualcuno possa modificarla.

+5

Penso che 'const char * const HELLO2' sia meglio .. – Shawn

Problemi correlati