2016-11-14 44 views
5

Znalazłem interesujący fakt i nie rozumiałem, jak to działa.
Poniższy fragment kodu działa doskonale.Rozmiar tablicy ze zmienną stałą w C

#include <stdio.h> 
int main(){ 
    const int size = 10; 
    int sampleArray[size]; 
    typedef char String [size]; 
    return 0; 
} 

Potem próbowałem użyć tylko i tylko stałej zmiennej o zasięgu globalnym, i nadal jest w porządku.

#include <stdio.h> 
const int size = 10; 
int main(){ 
    int sampleArray[size]; 
    typedef char String [size]; 
    return 0; 
} 


Ale jeśli zmienić zakres tablic do globalnego, a także, mam następujące:

error: variably modified ‘sampleArray’ at file scope

#include <stdio.h> 
const int size = 10; 
int sampleArray[size]; 
typedef char String [size]; 
int main(){ 
    return 0; 
} 

I nie rozumiem! Gdybym zastąpił zmienną stałą dla przykładu. do #define też byłoby w porządku.
Wiem, że zmienna #define jest wstępnie przetworzona i o ile mi wiadomo, zmienna stała jest tylko do odczytu. Ale co robi globalny zasięg mimo wszystko?

Nie rozumiem, jaki jest problem z trzecim kawałkiem kodu, jeśli drugi jest po prostu w porządku.

+3

Niektóre szczegóły: C ma obiekty "const", ale nie _constant_. Chociaż 'const' wydaje się implikować _konstant_, obiekt' const' nie jest _konstyntowy, ale bardziej przypomina "ten obiekt nie powinien się zmieniać, ale jeśli próba zmiany jest podjęta - kto wie, co może się stać?" W języku C prawdziwy _konstancję_ to kod taki jak "42", który jest stałą _integer_ z typem 'int'. Zatem 'const int size = 10;' nie jest zmienną _constant_. – chux

+0

Tablica nie ma stałego rozmiaru, ale jest tablicą o zmiennej długości. – Olaf

+1

Tak jak powiedzieli, C ma obiekty 'const', które są w rzeczywistości tylko do odczytu * zmiennymi *. Cf. C++, który ma prawdziwe obiekty 'const', które są w rzeczywistości * stałymi * kompilacją *. –

Odpowiedz

6

Tablice o zmiennej długości mogą mieć tylko automatyczny czas przechowywania. Umowy VLA zostały wprowadzone w C99.

Nie wolno deklarować VLA ze statycznym czas przechowywania, ponieważ wielkość VLA jest oznaczony w czasie wykonywania (patrz niżej)

Przed tym standardem można użyć makra jak

#define SIZE 10 

//... 

int a[SIZE]; 

lub wyliczający o wyliczenie jak

enum { SIZE = 10; } 

//... 

int a[SIZE]; 

Przy okazji można usunąć kwalifikator const i wystarczy napisać

int size = 10; 

zamiast

const int size = 10; 

(W C++ trzeba użyć const kwalifikatora choć w C++ nie ma Włas wyjątkiem tego, że niektóre kompilatory mogą mieć swoje własne rozszerzenia językowe)

Uwzględnij że operator sizeof dla VLA jest obliczany w czasie wykonywania zamiast czasu kompilacji.

+0

Dziękuję. Właśnie zacząłem rozumieć nieco więcej! Jednak jeśli próbuję bez const, mam ten sam błąd z globalnym zasięgiem. Ale z #define SIZE 10, to działa. –

+0

@ BálintPap Jak już pisałem, VLA może nie mieć stałego czasu przechowywania, który mają wszystkie globalne tablice. –

+0

A, zaczynamy, w porządku! Cóż, nigdy o tym nie myślałem. Dziękuję za wyjaśnienie! Doceniam to! –