2016-02-24 10 views
6

Il mio codice C era come segue:FILE * .. = stdout: Errore elemento inizializzatore non è costante

[Linux:/si/usr/hrl]vi test.c  

#include <stdio.h> 

FILE * hw = stdout; 

int main(void) 
{ 
     return 0; 
} 

Quando compilo su SUSE, che fanno l'errore del genere:

[Linux:/si/usr/hrl]cc test.c -o test 
test.c:3: error: initializer element is not constant 

Ho cercato il file di intestazione stdio.h e ho trovato che stdout sembra essere definito come una costante. Quindi, perché l'errore produce? A proposito, compilo lo stesso codice su AIX, risulta di successo.

+0

Hum. Come viene definito 'stdout' nell'implementazione della libreria standard C? Di che tipo è? – Bathsheba

+0

Non sembro così attento. Forse è quello 'extern struct _IO_FILE * stdout;/* Flusso di output standard. */'. A proposito, uso 'C++' e lo compilo, compilato con successo. – hrl

+1

@hrl Questa domanda è molto pertinente al punto che alcuni probabilmente direbbero che la tua domanda qui è un duplicato di essa: http://stackoverflow.com/questions/3025050/error-initializer-element-is-not-constant-when- try-to-initialize-variable-w –

risposta

4

La norma non richiede stdin, stdout e stderr come costanti.

Il progetto di n1256 per C99 dice in 7.19.1 ingresso/uscita <stdio.h>

L'intestazione dichiara ...
...
TMP_MAX
che si espande in un intero espressione costante ...

stderr stdin stdout
cui un re espressioni di tipo '' puntatore a file '' ...

(sottolineare il mio)

E 'esplicitamente dichiarato che alcuni altri valori sono costanti, mentre non si dice nulla per stdin, stdout e stderr

Quindi si deve mettere l'inizializzazione nel principale:

#include <stdio.h> 

FILE * hw; 

int main(void) 
{ 
     hw = stdout; 
     ... 
     return 0; 
} 

Nella libreria standard AIX, stdout è una costante, ma è solo un dettaglio di implementazione e non è possibile fare affidamento su di esso, in quanto potrebbe infrangere una versione più recente.

Ma non si deve fare affidamento su stdout come variabile (e nemmeno su lvalue), poiché è anche un dettaglio di implementazione nella libreria GCC.


Se non è possibile cambiare molto del codice, e solo bisogno di un GCC hack per rendere compilabile, si potrebbe tentare di utilizzare l'attributo costruttore estensione gcc .

Estratto gcc documentation

6.31 Dichiarazione Attributi di funzioni

in GNU C, si dichiara certe cose di funzioni chiamate nel programma che aiutano le chiamate di funzione compilatore ottimizzare e controllare il codice con più attenzione.

La parola chiave __attribute__ consente di specificare attributi speciali quando si effettua una dichiarazione.Questa parola chiave è seguita da una specifica di attributo all'interno di doppie parentesi. I seguenti attributi sono attualmente definite per le funzioni di tutti gli obiettivi: ..., costruttore, ...
...
L'attributo costruttore causa la funzione da chiamare automaticamente prima dell'esecuzione entrata principale() ...

Così si potrebbe usare:

#include <stdio.h> 

FILE * hw; 

void initHw(void) __attribute__((constructor)) { 
    hw = stdout; 
} 

int main(void) 
{ 
     return 0; 
} 

Ma ATTENTI: si tratta di un'estensione gcc, il che significa che il codice non è corretta C

+0

So che la tua modifica è corretta. Ma voglio cercare un modo per compilarlo correttamente senza inizializzarlo in 'main()'. Perché questo era un piccolo pezzo del programma che dovrei trapiantare Suse da AIX. È difficile per me modificare il codice reale come dici tu. – hrl

+0

@hrl: GCC ha molte estensioni non standard. Post modificato –

Problemi correlati