Domanda

Ho un progetto C in cui è organizzato tutto il codice *.c/*.h coppie di file e devo definire un valore costante in un file, che verrà comunque utilizzato anche in altri file.Come devo dichiarare e definire questo valore?

Dovrebbe essere come static const ... nel *.h file?COME extern const ... nel *.h file e definito nel file *.c file?In che modo è importante se il valore non è un tipo di dati primitivo (int, double, ecc), ma a char * o a struct?(Anche se nel mio caso è a double.)

Definire le cose dentro *.h files non sembra una buona idea in generale;si dovrebbero dichiarare le cose nel *.h file, ma definirli nel file *.c file.comunque, il extern const ... L'approccio sembra inefficiente, poiché il compilatore non sarebbe in grado di incorporare il valore, ma sarebbe invece necessario accedervi costantemente tramite il suo indirizzo.

Immagino che l'essenza di questa domanda sia:Bisognerebbe definire static const ... valori dentro *.h file in C, per poterli utilizzare in più posti?

È stato utile?

Soluzione

La regola seguo è quello di dichiarare solo le cose nei file H e definirli in file C. È possibile dichiarare e definire in un unico file C, ammesso che sarà utilizzato solo in quel file.

Con dichiarazione, intendo informare il compilatore della sua esistenza, ma non allocare spazio per essa. Questo include #define, typedef, extern int x, e così via.

Definizioni assegnano valori alle dichiarazioni e allocare spazio per loro, come int x e const int x. Questo include definizioni di funzione; compresi questi in file di intestazione spesso portare a spazio di codice sprecato.

Ho visto troppi programmatori juniores si confondono quando hanno messo const int x = 7; in un file di intestazione e poi ci domandiamo perché ottengono un errore di collegamento per x essere definito più di una volta. Credo che a un minimo indispensabile, si avrebbe bisogno static const int x in modo da evitare questo problema.

Non vorrei essere troppo preoccupato per la velocità del codice. Il problema principale con i computer (in termini di velocità e di costo) molto tempo fa spostata da velocità di esecuzione alla facilità di sviluppo.

Altri suggerimenti

Se hai bisogno di costanti (costanti reali, di tempo di compilazione) puoi farlo in tre modi, inserendole nei file header (non c'è niente di male in questo):

enum {
    FOO_SIZE = 1234,
    BAR_SIZE = 5678
};

#define FOO_SIZE 1234
#define BAR_SIZE 5678

static const int FOO_SIZE = 1234;
static const int BAR_SIZE = 5678;

In C++, tendo a utilizzare il metodo enum, poiché può essere compreso in uno spazio dei nomi.Per C, utilizzo la macro.Fondamentalmente però si tratta di una questione di gusti.Se hai bisogno di costanti in virgola mobile, non puoi più utilizzare l'enumerazione.In C++ utilizzo l'ultimo modo, static const double, in quel caso (nota che in C++ static sarebbe ridondante;diventerebbero statici automaticamente poiché sono const).In C, continuerei a utilizzare le macro.

È un mito che l'utilizzo del terzo metodo rallenterà in qualche modo il tuo programma.Preferisco semplicemente l'enumerazione poiché i valori che ottieni sono rvalue: non puoi ottenere il loro indirizzo, che considero una sicurezza aggiuntiva.Inoltre, viene scritto molto meno codice standard.L'occhio è concentrato sulle costanti.

Hai davvero bisogno di preoccuparsi per il vantaggio di linea? A meno che non si sta scrivendo codice embedded, il bastone di leggibilità. Se è davvero un numero magico di qualcosa, mi piacerebbe utilizzare una definizione; Credo che const è meglio per cose come const stringhe di versione e modificare gli argomenti chiamata di funzione. Detto questo, la definiscono in .c, dichiarare in .h regola è sicuramente una convenzione abbastanza universalmente accettata, e non vorrei rompere solo perché si potrebbe salvare una ricerca della memoria.

Come regola generale, non si definisce cose come static in un colpo di testa. Se lo fai definire #define variabili in un'intestazione, ogni file che utilizza l'intestazione ottiene la propria copia privata di tutto ciò che è dichiarato extern, che è l'antitesi di DRY principio: Don 't ripetersi .

Quindi, è necessario utilizzare un'alternativa. Per tipi interi, utilizzando enum (definito in un'intestazione) è molto potente; funziona bene con debugger troppo (anche se i debugger migliori possono essere in grado di aiutare con const valori macro troppo). Per i tipi non interi, una dichiarazione <=> (opzionalmente qualificato con <=>) nell'intestazione e una definizione in un file C è solitamente il modo migliore per andare.

Mi piacerebbe vedere più contesto per la tua domanda. Il tipo del valore è critica, ma hai lasciato fuori. Il significato della parola chiave const in C è molto sottile; per esempio     char const * p; non significa che puntatore p è una costante; è possibile scrivere p tutti che ti piace. Quello che non si può scrivere è la memoria che p punta a, e questo rimane vero anche come cambia il valore di p. Questo è l'unico caso io capisco; in generale, il significato del sottile posizionamento di const mi sfugge. Ma questo caso particolare è estremamente utile per i parametri funzione perché estrae una promessa dalla funzione che la memoria i punti di argomento non sarà mutato.

C'è un altro speciale caso tutti dovrebbero conoscere: interi. Quasi sempre, costanti, numeri interi di nome dovrebbero essere definiti in un file .h come letterali enumerazione . tipi enum non solo consentono di costanti collegate al gruppo insieme in modo naturale, ma anche di consentire i nomi di queste costanti per essere visto nel debugger, che è un enorme vantaggio.

ho scritto decine di migliaia di righe di C; probabilmente centinaia Se provo a rintracciarlo. (Wc ~ / src / c / *. C dice 85 mila, ma alcuni di che si genera, e, naturalmente, c'è un sacco di codice C in agguato altrove). A parte i due casi circa, non ho mai trovato molto uso per const. Sarei lieto di apprendere una nuova, utile esempio.

posso darvi una risposta indiretta. In C ++ (al contrario di C) const implica static. Thatis dire in C ++ static const è la stessa cosa di <=>. Così che si racconta come quel corpo standard C ++ si sente in merito alla questione vale a dire tutti i <=> s dovrebbero essere statico.

per l'ambiente autoconf: È sempre possibile definire costanti nel file di configurazione pure. AC_DEFINE () credo che è la macro per definire tutta la costruzione.

Per rispondere l'essenza della tua domanda:
È generalmente non di voler definire una variabile statica in un file di intestazione.
Questo potrebbe causare di avere variabili duplicati in ogni unità di traduzione (file C) che includono l'intestazione.

variabili in un colpo di testa in realtà dovrebbe essere dichiarate extern dal momento che è la visibilità implicita. Vedi questa domanda per una buona spiegazione.

In realtà, la situazione potrebbe non essere così terribile, come il compilatore probabilmente convertire un tipo const ad un valore letterale. Ma non si potrebbe desiderare di avvalersi di tale comportamento, soprattutto se le ottimizzazioni sono disattivati.

In C ++, è necessario utilizzare sempre

const int SOME_CONST = 17;

per le costanti e mai

#define SOME_CONST 17

Definisce sarà quasi sempre tornare indietro e mordere in seguito. Const sono in lingua, e sono fortemente tipizzati, quindi non sarà possibile ottenere gli errori strani a causa di qualche interazione nascosto. Io metterei il const nel file di intestazione appropriata. Finché si tratta di #pragma una volta (o #ifndef x / x #define / #endif), non potrà mai ottenere qualsiasi errori di compilazione.

In vaniglia C, si potrebbe avere problemi di compatibilità in cui è necessario utilizzare #defines.

Se si vuole il valore inline nelle funzioni si dovrebbe usare #define MY_MAGIC_NUMBER 0x12345678
Anche un static const unsigned MY_MAGIC_NUMBER = 0x12345678 causerà un valore di richiamo da indirizzi. La penalizzazione delle prestazioni non sarà davvero importa a meno che il valore molto in loop.
Io uso solo const per gli argomenti della funzione.

C'è stato qualche commento e giù per voto su questa risposta così ho provato la mia ipotesi e visto l'assembly generato e questa risposta è sbagliata. Fondamentalmente #define e <=> darà lo stesso risultato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top