Quando e per quali scopi deve essere usata la parola chiave const in C per le variabili?

48

Pur ricevendo il mio codice ha esaminato qui il problema dell'utilizzo di const parola chiave arrivata. Capisco che sia usato per implementare il comportamento di sola lettura sulle variabili.

Sono confuso su quali sono le varie situazioni in cui può essere utile.

  • Dovrebbe essere usato per motivi di chiarezza nei prototipi di funzioni?
  • Dovrebbe essere usato come misura di sicurezza durante lo sviluppo del codice?
  • Dovrebbe essere utilizzato nell'ambito di varie funzioni per la dichiarazione delle costanti di runtime?
  • Dovrebbe essere usato affatto?

Queste domande sono solo esempi della confusione che sto affrontando. La confusione generale è

  • Quando dovrebbe essere la parola chiave const utilizzata nella programmazione C?
  • Quali sono i vari tipi di benefici che si possono ottenere usando questa parola chiave in C?
  • Ci sono dei contro di usare const keyword?

È stato sottolineato che questa domanda potrebbe essere troppo ampia a causa di tutte queste domande nei dettagli della mia domanda. Volevo solo chiarire che queste domande servono solo a chiarire la confusione relativa alla domanda principale.

When and for what purposes should the const keyword be used in C for variables?

Può anche essere riformulato come

The proper use of const keyword in C' with the pros and cons of the same.

    
posta Aseem Bansal 11.07.2013 - 16:04
fonte

4 risposte

55

Durante la revisione del codice, applico le seguenti regole:

  • Usa sempre const per i parametri di funzione passati per riferimento dove il la funzione non modifica (o libera) i dati puntati a.

    int find(const int *data, size_t size, int value);
    
  • Usa sempre const per le costanti che potrebbero altrimenti essere definite usando un #define o un enum. Il compilatore può trovare i dati nella memoria di sola lettura (ROM) come risultato (sebbene il linker sia spesso uno strumento migliore per questo scopo nei sistemi embedded).

    const double PI = 3.14;
    
  • Non utilizzare mai const in una funzione prototype per un parametro passato Valore . Non ha significato ed è quindi solo 'rumore'.

    // don't add const to 'value' or 'size'
    int find(const int *data, size_t size, const int value); 
    
  • Se appropriato, utilizza const volatile in posizioni che non possono essere modificate dal programma ma potrebbero comunque cambiare. I registri hardware sono il caso d'uso tipico qui, ad esempio un registro di stato che riflette uno stato del dispositivo:

    const volatile int32_t *DEVICE_STATUS =  (int32_t*) 0x100;
    

Altri usi sono opzionali. Ad esempio, i parametri di una funzione all'interno della funzione implementazione possono essere contrassegnati come const.

// 'value' and 'size can be marked as const here
int find(const int *data, const size_t size, const int value)  
{
     ... etc

o funzione restituisce valori o calcoli che si ottengono e non cambiano mai:

char *repeat_str(const char *str, size_t n) 
{
    const size_t len = strlen(str);
    const size_t buf_size = 1 + (len * n);
    char *buf = malloc(buf_size);
    ...

Questi usi di const indicano semplicemente che non cambierai la variabile; non cambiano come o dove è memorizzata la variabile. Il compilatore può ovviamente capire che una variabile non è cambiata, ma aggiungendo const gli permetti di farla rispettare. Questo può aiutare il lettore e aggiungere sicurezza (anche se le tue funzioni sono grandi o abbastanza complicato che questo faccia una grande differenza, probabilmente ne hai altri i problemi). Modifica - es. una funzione a 200 righe con codifica densa con loop nidificati e molti lunghi o nomi di variabili simili, sapendo che alcune variabili non possono cambiare facilità sottolineando in modo significativo. Tali funzioni sono state mal progettate o maintened.

Problemi con const . Probabilmente sentirai il termine "avvelenamento da cost". Ciò si verifica quando l'aggiunta di const a un parametro di funzione fa sì che 'constness' propagarsi.

Modifica - avvelenamento const: ad esempio nella funzione:

int function_a(char * str, int n)
{
    ...
    function_b(str);
    ...
}

se cambiamo str in const , dobbiamo quindi assicurarci che anche fuction_b tenga a const . E così via se function_b passa str a function_c , ecc. Come puoi immaginare questo potrebbe essere doloroso se si propaga in molti file / moduli separati. Se si propaga in una funzione che non può essere cambiato (es. una libreria di sistema), quindi diventa necessario un cast. Quindi aspersione const around nel codice esistente sta forse chiedendo problemi. Nel nuovo codice tuttavia, è preferibile che const si adatti coerentemente laddove appropriato.

Il problema più insidioso di const è che non era nell'originale linguaggio. Come componente aggiuntivo, non si adatta perfettamente. Per cominciare ha due significati (come nelle regole precedenti, che significa "Non ho intenzione di cambiare questo" e "questo non può essere modificato"). Ma più di questo, può essere pericoloso. Ad esempio, compilare e eseguire questo codice e (a seconda del compilatore / opzioni) potrebbe andare in crash quando eseguire:

const char str[] = "hello world\n";
char *s = strchr(str, '\n');
*s = '
int find(const int *data, size_t size, int value);
';

strchr restituisce un char* non un const char* . Come il suo parametro di chiamata è const deve eseguire il cast il parametro call a char* . E in questo caso quello getta via la vera proprietà di archiviazione di sola lettura. Modifica: - questo vale in generale per i vars nella memoria di sola lettura. Per "ROM", intendo non solo la ROM fisica ma qualsiasi memoria protetta da scrittura, come accade alla sezione di codice dei programmi eseguiti su un sistema operativo tipico.

Molte funzioni di libreria standard si comportano allo stesso modo, quindi fai attenzione: quando tu avere costanti reali (ad esempio memorizzate nella ROM), devi stare molto attento a non farlo perdere la loro costanza.

    
risposta data 13.07.2013 - 16:05
fonte
7

Generalmente in qualsiasi linguaggio di programmazione si consiglia di utilizzare const o il modificatore equivalente poiché

  • Può chiarire al chiamante che ciò che hanno passato non cambierà
  • Potenziali miglioramenti di velocità dal momento che il compilatore sa per certo che può omettere alcune cose che sono rilevanti solo se il parametro può cambiare
  • Protezione da te stesso modificando accidentalmente il valore
risposta data 11.07.2013 - 17:05
fonte
1

Sì, è fondamentalmente la risposta di TheLQ.

È una misura di sicurezza per il programmatore in modo da non modificare una variabile e per non chiamare funzioni che potrebbero modificarle. In una matrice o struttura lo specificatore const indica che i valori dei loro contenuti non saranno modificati, e anche il compilatore non ti permetterà di farlo. Puoi comunque cambiare facilmente il valore della variabile con un cast.

In quello che ho visto di solito, è principalmente usato per aggiungere valori costanti nel codice e per indicare che la matrice o la struttura non saranno modificate se chiami una particolare funzione. Quest'ultima parte è importante, perché quando chiami una funzione che modificherà la tua matrice o struttura, potresti voler mantenere la versione originale, così creerai una copia della variabile e poi la passerai alla funzione. Se questo non è il caso, non hai bisogno della copia, ovviamente, quindi ad esempio puoi cambiare,

int foo(Structure s);

a

int foo(const Structure * s);

e non ottenere l'overhead della copia.

Solo per aggiungere, nota che C ha regole particolari con lo specificatore const. Ad esempio,

int b = 1;
const int * a = &b;

non è uguale a

int b = 1;
int * const a = &b;

Il primo codice non ti consentirà di modificare a. Nel secondo caso, il puntatore è costante ma il suo contenuto non lo è, quindi il compilatore ti permetterà di dire * a = 3; senza un errore del compilatore, ma non puoi rendere a come riferimento ad un'altra cosa.

    
risposta data 13.07.2013 - 15:09
fonte
0

In accordo con le dichiarazioni di TheLQ:

Quando si lavora con un gruppo di programmatori che dichiarano const è un buon modo per indicare che tale variabile non deve essere modificata, o solo per ricordare se stessi in progetti di grandi dimensioni. È utile in questo senso e può far risparmiare molti mal di testa.

    
risposta data 13.07.2013 - 14:19
fonte

Leggi altre domande sui tag