Tablica z nieznaną ilością elementów przy kompilacji

0

Witam.
W "Symfonii C++" przeczytałem: "Rozmiar tak definiowanej tablicy musi być stałą całkowitą - i to znaną już w takcie kompilacji. Kompilator bowiem musi już wtedy wiedzieć ile miejsca ma zarezerwować na daną tablicę".

Do tego jest przykład w którym jest błąd.
Przykład jest bardzo podobny do programu, który napisałem, a w którym błędu nie ma:

#include<cstdio>

int main()
{

    int n;
    printf("Wprowadz ilosc elementow tablicy ");
    scanf("%d",&n);
    int a[n];
    printf("Wprowadz elementy tablicy\n");

    for(int i=0;i<n;i++)   // wprowadzanie elementow tablicy
        scanf("%d",&a[i]);

    printf("\nElementy tablicy to:");

    for(int i=0;i<n;i++)
        printf("\n%d", a[i]);   // wypisywanie elementow tablicy

    return 0;

}

Tutaj mam pytanie - skoro taki program się kompiluje, to skoro kompilator ma wiedzieć w czasie kompilacji jaki rozmiar ma mieć tablica, to czy w tym wypadku rezerwuje miejsce w pamięci na 2^31 zmiennych typu int?
Bo w takim razie taki zabieg jest kompletnie nieopłacalny ze względu na marnowanie pamięci. Wcześniej myślałem, że C++ tworzy sobie takie tablice podczas działania programu (i zajmuje dzięki temu tyle pamięci ile wynosi wprowadzone n), dlatego się pytam jak to jest z tą zajętą pamięcią.

2

W sumie coś takiego jest ok, ale jest to rozszerzenie kompilatora, a co za tym idzie innym kompilatorem tego nie skompilujesz. Np. MSVC++ na coś takiego nie zezwala. Nie jestem pewien, ale to chyba działa tylko w gcc.

Raczej powinno się stosować zwykłe tablice dynamiczne:

int n, *tab;
cin >> n;
tab = new int[n];
...
delete [] tab;
0

Jeśli tak to ok, dzięki za odpowiedź.

1

Tutaj mam pytanie - skoro taki program się kompiluje, to skoro kompilator ma wiedzieć w czasie kompilacji jaki rozmiar ma mieć tablica
Nie wie. Nie musi - wie w czasie wykonania.

to czy w tym wypadku rezerwuje miejsce w pamięci na 2^31 zmiennych typu int?
dwa gigabajty? oj dużo by to było…

1

Po pierwsze 231 intów daje 233 bajtów czyli aż 8 GB!
Po drugie, gcc pozwala na tablicę o zmiennej wielkości, ale nawet jeśli rozmiar byłby stały (i duży) to odradzałbym definiować takie tablice lokalnie, bo w tej formie umieszczane są one na stosie, czym łatwo doprowadzić do przepełnienia stosu.
Najbezpieczniej stosować std::vector, który opakowuje obsługę allocowanych na stercie tablic.

1

Jak napisał byku_guzio, to jest rozszerzenie kompilatora, i w tym wypadku program zarezerwuje tyle miejsca, ile potrzeba, ale na stosie. I nie ma żadnych bound-checków, więc przy zbyt dużych danych możesz nadpisać stos i dostać segmentation fault -- jak zmienisz np. adres powrotu. Stos ma też bardziej ograniczoną pamięć od sterty. Ponadto taka tablica będzie lokalna dla funkcji, ale akurat w main() nie stanowi to większego problemu. ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1