2012-05-20 16 views
6

Powiel możliwe:
can we give size of static array a variableDlaczego nie można zmienić rozmiaru tablicy statycznej?

ja definiując tablicę w jednym z plików podrzędnych następująco.

static int arr[siz]; 

Tutaj siz jest zmienną globalną dostępną dla pliku podrzędnego. Ale kompilator gcc produkuje następujący błąd:

<filename>: <line_num> : error : storage size of ‘arr’ isn’t constant 

Dlaczego nie mogę zdefiniować static tablicę zmiennym rozmiarze?

EDYCJA: To wydaje się być problemem tylko dla typu static int. Jeśli zmienię typ zmiennej arr z static int na int, błąd zniknie, mimo że rozmiar tablicy nadal zależy od zmiennej siz.

Odpowiedz

8

Ponieważ rozmiar deklarowanej macierzy nie jest stały, macie Państwo tablicę zmiennych o zmiennej długości (VLA) . VLA są dozwolone przez standard c99, ale wiążą się z nim pewne ograniczenia. Nie można mieć tablicy o zmiennej długości ze specyfikatorem klasy pamięci masowej static lub extern.

Masz umowę VLA ze specyfikacją przechowywania static i nie jest to dozwolone przez standard C99.

odniesienia:

C99 standardowy: 6.7.5.2/8

Przykład 4 wszystkie deklaracji różnie modyfikowany fi ed (VM) typu muszą być w każdym zakresie bloku lub prototypowej funkcji zakresu. Obiekty tablicy zadeklarowane w specyfikacji statycznej lub zewnętrznej klasy pamięci nie mogą mieć tablicy o zmiennej długości (VLA) typu. Jednak obiekt zadeklarowany ze statyczną specyfikacją klasy pamięci może mieć typ maszyny wirtualnej (czyli wskaźnik do typu VLA). Wreszcie, wszystkie identyfikatory zadeklarowane za pomocą typu VM muszą być zwykłymi identyfikatorami i dlatego nie mogą być członkami struktur lub związków.

Jeśli chcesz mieć tablicę o wymiarach dynamicznych ze specyfikatorem pamięci static, musisz użyć tablicy dynamicznej przydzielonej do sterty.

#define MAX_SIZE 256 
static int* gArr; 
gArr = malloc(MAX_SIZE * sizeof(int)); 

EDIT:
Aby odpowiedzieć zaktualizowaną pytanie:
Po usunięciu słowa kluczowego static od zgłoszenia, specifier przechowywanie deklarowanych zmian tablicę z static globalne, należy zwrócić uwagę na standardowe cytat powyżej, wyraźnie wspomina o ograniczeniu, że umowy VLA są niedozwolone przy przechowywaniu specyfikacji static i extern. Oczywiście, możesz mieć VLA z globalną specyfikacją pamięci, która jest po usunięciu słowa kluczowego static.

+0

Dzięki za dobrze zbadaną odpowiedź. – Abhinav

+0

Tak skutecznie, jeśli używam gcc-4.3, VLA nie są dozwolone dla zmiennych typu zewnętrznego i statycznego? Oto, co odpowiedział również DCoder użytkownika w komentarzu w innej odpowiedzi. – Abhinav

+0

@Abhinav: Tak, masz rację. Warianty VLA są niedozwolone dla zmiennych ze specyfikacją przechowywania typu "zewnętrznego" i "statycznego". Używasz gcc-4.3, który jest kompatybilny ze standardem c99. Zmieniono odpowiedź na adres edytowanego zapytania. –

2

Przydzielasz tablicę w czasie kompilacji, więc kompilator musi wcześniej znać jej rozmiar. Musisz zadeklarować siz jako stałej ekspresji zanim zadeklarować arr, na przykład:

#define siz 5 

lub

enum ESizes 
{ 
    siz = 5 
}; 

lub

const int siz = 5; 

Ewentualnie, jeśli trzeba określić jego rozmiar w czas działania, możesz go przydzielić na kupę, używając: :

static int* arr; 
arr = (int*)malloc(siz * sizeof(int)) 

EDIT: jak wspomniał eddieantonio, moja odpowiedź jest ważna dla C89. W C99 można zadeklarować tablice o zmiennej wielkości.

+0

Twój przykład "const" się nie liczy. Zobacz https://stackoverflow.com/a/18848583 –

1

Nie można zdefiniować żadnej tablicy o rozmiarze zmiennym. Dzieje się tak, ponieważ arr[siz] sprawia, że ​​kompilator (!) Alokuje pamięć dla twojej tablicy (cóż, kompilator tworzy program, który ..., ale nie zagłębiajmy się w szczegóły). Jednak zmienne mogą być zmieniane w środowisku wykonawczym (!), Co oznacza, że ​​kompilator nie ma szans na określenie ilości pamięci do przydzielenia.

Co można zrobić, to

static int* arr; 
arr = (int*) calloc(siz,sizeof(int)) 

linie te wynikają w programie, który przydziela pamięć na starcie, dlatego jest to dokładny rozmiar może być określony w czasie wykonywania, jak również.

+3

[C99 zezwala na tablice o zmiennej długości] (http://stackoverflow.com/questions/7696591/can-we-give-size-of-static-array-a- zmienna), o ile nie są statyczne, a nie zewnętrzne. "Wszystkie deklaracje typów zmiennie zmodyfikowanych (VM) muszą być w zasięgu bloku lub zakresie prototypu funkcji Obiekty tablicy zadeklarowane ze statycznym lub zewnętrznym specyfikatorem klasy pamięci nie mogą mieć typu tablicy zmiennej (VLA)." – DCoder

+0

@DCoder Używam gcc 4.3. Dziękuję za konstruktywny komentarz. – Abhinav

+4

@ paulsm4, twój ton jest po prostu obraźliwy, zazwyczaj SO jest przyjaznym miejscem –

0

Nie można zadeklarować tablicy static o rozmiarze zmiennym, ponieważ jej przestrzeń jest przydzielona w Data Segment (lub bss segment w przypadku niezainicjowanej zmiennej). W związku z tym kompilator musi znać rozmiar w czasie kompilacji i będzie narzekał, jeśli rozmiar nie jest stały.

Przyczyną tego jest rozmiar segmentu danych, który przyczynia się do rozmiaru generowanego pliku wykonywalnego, który oczywiście jest tworzony w czasie kompilacji i dlatego musi zostać naprawiony.

Powiązane problemy