2013-08-10 21 views
8

Mam program z niektórych globalnych ciągów zdefiniowanych na początku pliku jak poniżej:C: Przypisywanie "static const char * const" do "const static char *"

static const char * const STRING_A = "STRING A"; 
static const char * const STRING_B = "STRING B"; 

Następnie w programie głównym loop I wielokrotnie wywołuje funkcję. Ta funkcja zawiera wskaźnik, który ma wskazywać powyższe łańcuchy, w zależności od wprowadzonego przez użytkownika. Domyślnie chcę być ustawiony na STRING_A, więc to, co w istocie ma to:

// Called repeatedly from a loop. 
void input_function() 
{ 
    static const char *current = STRING_A; 

    // Do stuff and reassign different strings to "current" 
    ... 
} 

Problem, który mam jest to, że podczas kompilacji otrzymuję „Błąd: Element Inicjator nie jest stała”. Używa się GCC 4.7.2. Co bardziej mnie myli, to, że błąd zniknie, jeśli pozbędę się słowa kluczowego "static" w funkcji wejściowej. Nie jest to jednak rozwiązanie, ponieważ słowo kluczowe static jest potrzebne do śledzenia bieżącego ciągu znaków między wywołaniami.

Oczywiście mogłem to naprawić na wiele sposobów, najprościej mówiąc, po prostu pozbywając się niektórych z kwalifikatorów const. Ale chcę zrozumieć, dlaczego to nie działa.

Moje bieżące zrozumienie polega na tym, że globalne zmienne łańcuchowe nie mogą być modyfikowane w celu wskazania różnych ciągów znaków, a także nie można modyfikować ich indywidualnych znaków. Statyczne słowo kluczowe powoduje, że są one lokalne dla pliku źródłowego.

Dla zmiennej w mojej funkcji rozumiem, że słowo kluczowe static pozwala zachować jej wartość przez wiele wywołań funkcji, i że kwalifikator const w tym przypadku oznacza, że ​​ciąg wskazany przez current może się zmienić - ale nie znaki ciągu, który wskazuje.

Nie widzę żadnych konfliktów w tych stwierdzeniach, więc nie rozumiem, dlaczego kompilator daje błąd - szczególnie, dlaczego nie ma problemu, jeśli usunięto "statyczny" specyfikator current.

Dzięki, jeśli ktoś może wyjaśnić, na czym polega problem.

Odpowiedz

7

6.7.8/4 [C99]

All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.

STRING_A nie jest, a więc błąd.

One sposób, aby obejść ten będzie zgodnie z poniższymi wytycznymi:

void input_function() 
{ 
    static const char *current = NULL; 
    if (current == NULL) { 
     current = STRING_A; 
    } 

    ... 
} 
+0

jestem nadal zawijania moja głowa wokół niego, ale dzięki za szybką odpowiedź. –

3

To dlatego STRING_A nie jest stałą czasu kompilacji. Twoje interpretacje są poprawne, jednak nie możesz zainicjować stałej jako wartości niestałej (takiej jak STRING_A).

W jaki sposób kompilator wie, co STRING_A wskazuje podczas kompilacji? Nie oznacza to, że STRING_A wskazuje na różne adresy w sekcji pamięci tylko do odczytu przy każdym wykonaniu programu, w zależności od tego, gdzie literał ciągu znajduje się w pamięci.

Trzeba by wykonać następujące czynności w celu obejścia tego przymusu podczas odnoszące ten sam efekt:

// Defines current to be a null pointer. 
static const char *current = NULL; 

// Determine if current is a null pointer. 
if (current == NULL) current = STRING_A; 
+0

Dzięki za szybką odpowiedź, musiałem dać NPE, ponieważ był jeszcze szybszy. Dzięki jeszcze raz. –