2012-02-09 153 views
24

Otrzymuję błąd, gdy próbuję utworzyć tablicę ze zmiennych, które zadeklarowałem.Tablica C++ - wyrażenie musi mieć stałą wartość

int row = 8; 
int col= 8; 
int [row][col]; 

Dlaczego mam ten błąd:

expression must have a constant value.

+0

Czego można się spodziewać po 'int [row] [col];' –

+0

Dobre książki w języku C++ wymienione tutaj: http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list –

+5

Nie edytuj kodu zapytania z poprawką; to sprawia, że ​​twoje pytanie jest bardzo mylące dla przyszłych czytelników. – ildjarn

Odpowiedz

14

C++ nie zezwala na wartości niż stałe dla rozmiaru tablicy. Tak po prostu został zaprojektowany.

C99 pozwala rozmiarowi tablicy być zmienną, ale nie jestem pewien, czy jest dozwolona dla dwóch wymiarów. Niektóre kompilatory C++ (gcc) zezwalają na to jako rozszerzenie, ale może być konieczne włączenie opcji kompilatora, aby na to zezwolić.

I prawie o tym zapomniałem - musisz zadeklarować nazwę zmiennej, a nie tylko wymiary tablicy.

+0

"ale nie jestem pewien, czy jest dozwolony na dwa wymiary" - tak. Dla C, jak zauważyłeś, nie dla C++. – hvd

+0

@hvd, dzięki za wyjaśnienia. Moja ekspozycja na czyste C w tych dniach jest niestety ograniczona. –

29

Podczas tworzenia takiej tablicy jej rozmiar musi być stały. Jeśli chcesz dynamicznie wielkości tablicę, trzeba przydzielić pamięci dla niej na stercie i będziesz też musiał uwolnić go z delete kiedy skończysz:

//allocate the array 
int** arr = new int*[row]; 
for(int i = 0; i < row; i++) 
    arr[i] = new int[col]; 

// use the array 

//deallocate the array 
for(int i = 0; i < row; i++) 
    delete[] arr[i]; 
delete[] arr; 

Jeśli chcesz stały rozmiar, a następnie muszą być zadeklarowane const:

const int row = 8; 
const int col = 8; 
int arr[row][col]; 

również

int [row][col]; 

nawet nie dostarczyć nazwę zmiennej.

+4

Może pokazać, jak usunąć pamięć, co? ;) – monoceres

8

Standard wymaga, aby długość tablicy była wartością obliczalną w czasie kompilacji, aby kompilator mógł przydzielić wystarczającą ilość miejsca na stosie. W twoim przypadku próbujesz ustawić długość tablicy na wartość nieznaną w czasie kompilacji. Tak, wiem, że wydaje się oczywiste, że powinien on być znany kompilatorowi, ale tak nie jest w tym przypadku. Kompilator nie może przyjąć żadnych założeń dotyczących zawartości zmiennych niestanowiących stałych. Więc jedź z:

const int row = 8; 
const int col= 8; 
int a[row][col]; 

UPD: niektóre kompilatory pozwolą ci je usunąć. IIRC, g ++ ma tę funkcję. Jednak nigdy go nie używaj, ponieważ twój kod stanie się nieprzynoszący na kompilatorach.

+1

Najbardziej zwięzła i poprawna odpowiedź. –

4

Kiedy deklarujesz zmienną jak tutaj

int a[10][10]; 

mówisz kompilator C++, który ma zostać przydzielone 100 kolejnych liczb całkowitych w pamięci programu przy starcie. Kompilator zapewni wtedy, że twój program będzie miał tak dużo dostępnej pamięci i wszystko będzie dobrze ze światem.

Jeśli jednak poinformować kompilator

int x = 9001; 
int y = 5; 
int a[x][y]; 

kompilator nie ma możliwości dowiedzenia się, ile pamięci w rzeczywistości będzie potrzebował w czasie pracy, nie robiąc wiele bardzo skomplikowanej analizy wyśledzić każdą ostatnią miejsce gdzie zmieniły się wartości x i y [jeśli są]. Zamiast obsługi takich tablic o zmiennych rozmiarach, C++ i C zdecydowanie sugerują, czy nie wymagają użycia malloc(), aby ręcznie przydzielić żądaną przestrzeń.

TL; DR

int x = 5; 
int y = 5; 
int **a = malloc(x*sizeof(int*)); 
for(int i = 0; i < y; i++) { 
    a[i] = malloc(sizeof(int*)*y); 
} 

a jest obecnie 2D Tablica wielkości 5x5 i działają tak samo, jak int A [5], [5]. Ponieważ zostały ręcznie przydzielone pamięci, C++ i C popyt że go usunąć ręcznie też ...

for(int i = 0; i < x; i++) { 
    free(a[i]); // delete the 2nd dimension array 
} 
free(a); // delete a itself 
+1

Twoja odpowiedź jest nieprawidłowa C++: polegasz na niejawnej konwersji z 'void *' na 'int *' i 'int **'. I oczywiście, jeśli dodasz obsadę, nadal jest to zły styl, aby w ogóle używać 'malloc'. – hvd

-2

Nie, to nie musi być stała, dlatego powyżej jego kod jest źle dlatego, że potrzebuje dołączyć nazwę zmiennej przed deklaracją.

int row = 8; 
int col= 8; 
int x[row][col]; 

w Xcode, które skompilować i uruchomić bez żadnych problemów, w M $ kompilator C++ .NET nie będzie kompilować, to narzekają, że nie można używać non const dosłownego zainicjować tablicę, potrzeby rozmiar być znanym w czasie kompilacji

7

Możesz użyć #define jako alternatywnego rozwiązania, które nie wprowadza wektora i malloc, i nadal używasz tej samej składni podczas definiowania tablicy.

#define row 8 
#define col 8 

int main() 
{ 
int array_name[row][col]; 
} 
Powiązane problemy