2016-02-24 9 views
6

Mój kod C było następujące:FILE * .. = stdout: Błąd elementem Inicjator nie jest stała

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

#include <stdio.h> 

FILE * hw = stdout; 

int main(void) 
{ 
     return 0; 
} 

Kiedy skompilować na SUSE to zrobić błąd tak:

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

Mam szukać pliku nagłówkowego stdio.h i stwierdzić, że stdout wydaje się być zdefiniowana jako stała. Więc dlaczego błąd produkuje? Nawiasem mówiąc, kompiluję ten sam kod w systemie AIX, to jest wynikiem sukcesu.

+0

Hum. W jaki sposób zdefiniowano 'stdout' w implementacji biblioteki standardowej C? Jaki to jest typ? – Bathsheba

+0

Nie wyglądam tak ostrożnie. Może to ta "zewnętrzna struktura _IO_FILE * stdout;/* Standardowy strumień wyjściowy. */'. Przy okazji, używam 'C++' i kompiluję, skompilowałem się pomyślnie. – hrl

+1

@hrl To pytanie jest bardzo istotne dla punktu, który niektórzy prawdopodobnie powiedzieliby, że twoje pytanie tutaj jest jego duplikatem: http://stackoverflow.com/questions/3025050/error-initializer-element-is-not-constant-when- probing-to-initialize-variable-w –

Odpowiedz

4

Standard nie wymaga, aby stdin, stdout i stderr były stałymi.

Projekt n1256 do C99 mówi 7.19.1 Input/Output <stdio.h>

Nagłówek deklaruje ...
...
TMP_MAX
który rozszerza się do liczby całkowitej stała wyrażenie ...

stderr stdin stdout
których Re wyrażeń typu „” wskaźnik do pliku „” ...

(podkreślenie moje)

Jest jawnie stwierdził, że niektóre inne wartości są stałe, natomiast nic nie mówi o stdin, stdout i stderr

Więc należy umieścić w głównym inicjalizacji:

#include <stdio.h> 

FILE * hw; 

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

W bibliotece standardowej AIX, stdout jest stałą, ale jest to tylko szczegół implementacji i nie można na niej polegać, ponieważ może ona zostać złamana w dowolnej nowszej wersji.

Ale nie powinieneś polegać na tym, że stdout jest zmienną (ani nawet l-wartością), ponieważ jest to również szczegół implementacji w bibliotece GCC.


Jeśli nie można zmienić dużo kodu i po prostu potrzebują GCC włamać aby compilable, można spróbować użyć gcc atrybutu konstruktor rozszerzenie.

Wyciąg z gcc documentation

6.31 Deklarowanie atrybutów funkcji

W GNU C, zadeklarować pewne rzeczy o funkcji zwanych w programie, które pomagają wywołania funkcji kompilator zoptymalizować i sprawdzić swój kod bardziej ostrożnie.

Słowo kluczowe __attribute__ pozwala określić specjalne atrybuty podczas składania deklaracji.Po tym słowie kluczowym występuje specyfikacja atrybutu w podwójnym nawiasie. Następujące atrybuty są aktualnie zdefiniowane funkcje na wszystkich celów: ..., konstruktora ...
...
Atrybut konstruktor wywołuje funkcję być wywoływana automatycznie przed wejściem wykonanie main() ...

Więc można użyć:

#include <stdio.h> 

FILE * hw; 

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

int main(void) 
{ 
     return 0; 
} 

Ale UWAGA: to rozszerzenie gcc, co oznacza, że ​​kod jest prawidłowy nie C

+0

Wiem, że twoja edycja jest poprawna. Ale chcę szukać sposobu na skompilowanie go bez inicjowania go w 'main()'. Ponieważ to były małe fragmenty programu, które powinienem przeszczep do Suse z AIX. Trudno mi zmodyfikować prawdziwy kod, jak mówisz. – hrl

+0

@hrl: GCC ma wiele niestandardowych rozszerzeń. Post edytowany –

Powiązane problemy