2012-02-21 17 views
34

Rozumiem, że sprzęt ograniczy ilość pamięci przydzielonej podczas wykonywania programu. Jednak moje pytanie brzmi: bez względu na sprzęt. Zakładając, że nie ma limitu ilości pamięci, czy nie będzie limitu macierzy?Jaki jest maksymalny rozmiar tablicy w C?

+2

Właściwie oprogramowanie (OS) jest rzeczą, która powoduje normalnie limit pamięci widziane przez program C. – TJD

+2

Bez limitu pamięci nie ma ograniczenia rozmiaru wskaźnika. Bez limitu rozmiaru wskaźnika wszystkie zakłady są wyłączone. – dasblinkenlight

+4

byłby ograniczony przez rozmiar wskaźnika (32-bitowy w porównaniu do 64-bitowego). –

Odpowiedz

33

Nie ma stałe ograniczenie rozmiaru tablicy w C.

rozmiar każdego pojedynczego przedmiotu, w tym dowolnego obiektu matrycy jest ograniczona SIZE_MAX, wartości maksymalnej, która typu size_t jest wynikiem działania operatora sizeof. (Nie jest do końca jasne, czy standard C dopuszcza obiekty większe niż SIZE_MAX bajtów, ale w praktyce takie obiekty nie są obsługiwane, patrz przypis.) Ponieważ SIZE_MAX jest określony przez implementację i nie może być modyfikowany przez żaden program, który nakłada górną granicę z SIZE_MAX bajtów dla dowolnego pojedynczego obiektu.

Szerokość typu void*, ogólnego rodzaju wskaźnika, nakłada górne ograniczenie na całkowity rozmiar wszystkich obiektów w programie wykonawczym (który może być większy niż maksymalny rozmiar pojedynczego obiektu).

Norma C narzuca dolne krawędzie, ale nie górne, na te ustalone rozmiary. Żadna zgodna implementacja C nie może obsługiwać obiektów o nieskończonej wielkości, ale z zasady może obsługiwać obiekty o dowolnym skończonym rozmiarze. Górne ograniczenia są narzucane przez poszczególne implementacje C, przez środowiska, w których działają, i przez fizykę, a nie przez język.

Przykładowo Wykonanie zgodne może mieć SIZE_MAX równe 2 -1, co oznacza, że ​​może zasadniczo mają Obiekty do 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137215 bajtów.

Sprzęt do znalezienia szczęścia, który faktycznie obsługuje takie obiekty.

Przypis: Nie ma wyraźnej zasady, że żaden obiekt nie może być większy niż SIZE_MAX bajtów. Nie można z pożytkiem zastosować operatora sizeof do takiego obiektu, ale jak każdy inny operator, sizeof może przepełnić; to nie znaczy, że nie można wykonywać operacji na takim obiekcie. Ale w praktyce każda rozsądna implementacja będzie na tyle duża, że ​​będzie reprezentować rozmiar dowolnego obsługiwanego obiektu.

+0

Nie mogę użyć arbitralnej biblioteki precyzji, aby rozszerzyć to maksimum? Teoretycznie rzecz biorąc ...: p –

+1

@ J.C.Leitão: Zasadniczo, przypuszczam, że kompilator mógłby użyć dowolnej biblioteki precyzyjnej do implementacji bardzo szerokich typów liczb całkowitych. Ale nie możesz tego robić jako programista; rzeczywiste typy liczb całkowitych (z literałami, operatorami i tak dalej) są ograniczone do tego, co zapewnia kompilator. –

+0

Czy istnienie [daleko wskazujących wskaźników] (http://en.wikipedia.org/wiki/Far_pointer) i model koreańskiej pamięci zmieniają twoją odpowiedź w jakikolwiek sposób? – jfs

3

Chyba największa teoretyczna tablica byłaby maksymalna wartość „unsigned long” (czy jak największa liczba całkowita najnowszy standard/kompilator obsługuje)

5

Bez względu na pamięć, maksymalny rozmiar tablicy jest ograniczony przez typ liczby całkowitej używanej do indeksowania tablicy.

6

Maszyna 64-bitowa mogłaby teoretycznie adresować maksymalnie 2^64 bajty pamięci.

+0

Powodzenia w oddaniu tej ilości pamięci do komputera. Nawet z prawem Moore'a to już dawno. –

+0

Mogę sobie wyobrazić, że dzieje się to za mojego życia. –

+1

@AmigableClarkKant Cała * ziemia * składa się z mniej niż 2^64 atomów (waży tylko około 5 * 10^24 kg), więc twoje oczekiwania są * bardzo * * bardzo * nadmiernie optymistyczne. SCNR. – Durandal

2

Wielkość wskaźnika ograniczy dostęp do pamięci, do której można uzyskać dostęp. Nawet jeśli sprzęt oferuje obsługę nieograniczonej ilości pamięci, jeśli największym typem danych, który możesz wykorzystać, jest 64-bitowy, będziesz mieć dostęp tylko do 2^64 bajtów pamięci.

0

Szukałem sposobu na określenie maksymalnego rozmiaru tablicy. To pytanie wydaje się pytać o to samo, więc chcę podzielić się swoimi odkryciami.

Początkowo C nie udostępnia żadnej funkcji określającej maksymalną liczbę elementów możliwych do przydzielenia w tablicy w czasie kompilacji. Dzieje się tak dlatego, że zależy to od pamięci dostępnej w komputerze, w którym zostanie wykonana.

Z drugiej strony stwierdziłem, że funkcje przydzielania pamięci (calloc() i malloc()) umożliwiają przydzielanie większych tablic. Ponadto te funkcje umożliwiają obsługę błędów alokacji pamięci czasu wykonywania.

Nadzieję, że pomaga.

6

C99 5.2.4.1 „Granice Translation” minimalny rozmiar

Realizacja powinna być w stanie przetłumaczyć i wykonać co najmniej jeden program, który zawiera co najmniej jedno wystąpienie każdego z następujących granicach: 13)

  • 65535 bajtów na obiekcie (środowiska obsługiwanego wyłącznie)

13) Implementacje shou Unikam narzucania stałych limitów tłumaczeń, kiedy tylko jest to możliwe.

Sugeruje to, że zgodna implementacja może odmówić skompilowania obiektu (który zawiera tablice) o więcej niż short bajtów.

PTRDIFF_MAX wydaje się być praktyczna granica dla statycznej tablicy obiektów

C99 standardowych 6.5.6 Additive operatorów mówi:

9 Gdy dwa wskaźniki są odejmowane, oba powinny wskazywać elementy tego samego obiektu tablicy, lub jeden za ostatnim elementem obiektu tablicy; wynikiem jest różnica dolnych indeksów dwóch elementów tablicy. Rozmiar wyniku jest zdefiniowany w implementacji, , a jego typ (podpisany typ całkowity) to ptrdiff_t zdefiniowany w nagłówku <stddef.h>. Jeśli wyniku nie można przedstawić na obiekcie tego typu, zachowanie jest niezdefiniowane.

Co oznacza dla mnie, że tablice większe niż ptrdiff_t są dozwolone w teorii, ale wtedy nie można poruszyć różnicy ich adresów.

Być może z tego powodu GCC wydaje się ograniczać do ptrdiff_t. Jest również wymienione w: Why is the maximum size of an array "too large"?

I zweryfikowany empirycznie to z main.c:

#include <stdint.h> 

uint8_t a[(X)]; 

int main(void) { 
    return 0; 
} 

, a następnie w Ubunbu 17.10:

$ arm-linux-gnueabi-gcc --version 
arm-linux-gnueabi-gcc (Ubuntu/Linaro 7.2.0-6ubuntu1) 7.2.0 
Copyright (C) 2017 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

$ printf ' 
> #include <stdint.h> 
> PTRDIFF_MAX 
> SIZE_MAX 
> ' | arm-linux-gnueabi-cpp | tail -n2 
(2147483647) 
(4294967295U) 
$ PTRDIFF_MAX == 2147483647 == 2^31 - 1 
$ 
$ # 2lu << 30 == 2^31 == PTRDIFF_MAX + 1 
$ arm-linux-gnueabi-gcc -std=c99 -DX='(2lu << 30)' main.c 
a.c:5:9: error: size of array ‘a’ is too large 
uint8_t a[(X)]; 
     ^
$ 
$ # PTRDIFF_MAX 
$ arm-linux-gnueabi-gcc -std=c99 -DX='(2lu << 30) - 1lu' main.c 
$ 

Zobacz także

Powiązane problemy