2014-11-03 5 views
6

Dal 21 ° secolo C libro:inizializzazione variabile statica con un valore non costante

variabili statiche, anche quelli all'interno di una funzione, vengono inizializzati all'avvio del programma, prima principale, quindi non è possibile inizializzare loro con un valore non costante.

//this fails: can't call gsl_vector_alloc() before main() starts 
static gsl_vector *scratch = gsl_vector_alloc(20); 

Questo è un fastidio, ma facilmente risolto con una macro per iniziare a zero e allocare al primo utilizzo:

#define Staticdef(type, var, initialization) \ 
static type var = 0; \ 
if (!(var)) var = (initialization); 

//usage: 
Staticdef(gsl_vector*, scratch, gsl_vector_alloc(20)); 

Non capisco che differenza della macro fatto. Non fa esattamente la stessa cosa dopo la pre-elaborazione?


+0

Non una raccomandazione molto sicura da questo libro, ma più di un rapido e sporco trucco pericoloso. – alk

risposta

6

Non fa esattamente la stessa cosa dopo la pre-elaborazione?

No, entrambi non si comportano necessariamente allo stesso modo.

Questo initalisation è garantita a conduzione solo volta:

static int i = 42; /* Initialisation */ 

Questa assegnazione

static int i = 0; 
if (!i) /* line X */ 
    i = 42; /* Assignment */ 

non è, come ogni flusso programma raggiunge la linea X e i uguale a 0 quindi iè impostato a a 42 (di nuovo).

Esempi:

#include <stdio.h> 

void foo(int inew) 
{ 
    static int i = 42; 

    printf("%d\n", i); 

    i = inew; 
} 

void bar(int inew) 
{ 
    static int i = 0; 
    if (!i) 
    i = 42; 

    printf("%d\n", i); 

    i = inew; 
} 

int main(void) 
{ 
    foo(43); 
    foo(0); 
    foo(44); 

    printf("\n"); 

    bar(43); 
    bar(0); 
    bar(44); 

    return 0; 
} 

Esegui e vedere la differenza:

42 
43 
0 

42 
43 
42 
+1

Solo un chiarimento, il 'static int i = 0' viene eseguito solo una volta nel secondo esempio. Dopo questo il 'if (! I)' sarà sempre vero in questo esempio, quindi 'i = 42' sarà sempre chiamato. – Jite

+0

@Jite: ho aggiunto un esempio. – alk

+0

Hai ragione. Ho letto male la domanda. – Jite

3

preprocessore sostituisce solo il testo, in modo che il risultato finale di Staticdef macro è:

static gsl_vector *scratch = 0 ; 
if (!(scratch)) scratch = (gsl_vector_alloc(20)); 

È possibile digitare che voi stessi se si desidera o utilizzare la macro.

Questo è ovviamente diversa rispetto alla versione non corretta:

static gsl_vector *scratch = gsl_vector_alloc(20); 

non consiglia di utilizzare la macro in quanto non può essere avvolto in un do {} po ', e offusca solo il codice.