C ++ 'da bir maksimum dizi uzunluğu sınırı var mı?


183

C ++ 'da bir dizi için maksimum uzunluk var mı?

Bir C ++ sınırı mı yoksa makineme bağlı mı? Tweakable mı? Dizinin türüne bağlı mı?

Bir şekilde bu sınırı kırabilir miyim yoksa daha iyi bilgi depolamanın yolunu mu aramak zorundayım? Ve en basit yol ne olmalı?

Ne yapmam gereken bir dizi uzun uzun int depolamak, bir Linux ortamında çalışıyorum. Benim sorum: N> 10 basamaklı bir N uzun uzun tamsayı dizisini saklamam gerekirse ne yapmam gerekir?

Buna ihtiyacım var çünkü okul için bazı kriptografik algoritmalar (örneğin p-Pollard gibi) yazıyorum ve tamsayı duvarına ve dizilerin temsil uzunluğuna çarpıyorum.

Yanıtlar:


163

Her ikisi de C ++ tarafından değil, donanım tarafından uygulanan iki sınır vardır.

İlk sınıra (asla ulaşılmaması gerekir), dizideki bir dizini (ve bunların boyutunu) tanımlamak için kullanılan boyut türünün kısıtlamaları tarafından belirlenir. Sistemin std::size_talabileceği maksimum değerle verilir . Bu veri türü, boyutu herhangi bir nesnenin bayt cinsinden içerecek kadar büyüktür

Diğer sınır fiziksel bir hafıza sınırıdır. Dizideki nesneleriniz ne kadar büyük olursa, bellek dolu olduğu için bu sınıra o kadar çabuk ulaşılır. Örneğin, vector<int>belirli bir n boyutundaki a tipik olarak bir tür diziden vector<char>(eksi küçük bir sabit değer) birden fazla bellek alır , çünkü intgenellikle daha büyüktür char. Bu nedenle, a vector<char>, vector<int>bellek dolmadan önceki öğeden daha fazla öğe içerebilir . Aynı ham C tarzı diziler int[]vechar[] .

Buna ek olarak, bu üst sınır, allocatoryapılandırmak için kullanılan türden etkilenebilir , vectorçünkü a allocatorhafızayı istediği şekilde yönetmekte serbesttir. Çok garip ama yine de akla gelebilecek bir ayırıcı, bir nesnenin özdeş örnekleri kaynakları paylaşacak şekilde belleği bir araya getirebilir. Bu şekilde, bir konteynere aksi takdirde kullanılabilir tüm belleği kullanacak birçok özdeş nesne ekleyebilirsiniz.

Bunun dışında, C ++ herhangi bir sınır koymaz.


20
Ayrıca, özellikle uygulamaya özel olan (ancak değiştirilebilen) dişler kullanılıyorsa, normalde yığın boyutu sınırlarına kolayca vurabilirsiniz.
Alaric

@Alaric: Doğru. Sistem özelliklerine çok fazla girmek istemedim çünkü çok farklılar ve hiçbirinde uzman değilim.
Konrad Rudolph

@Konrad, ayırıcı türleri hakkında ilginç bir nokta ve farkında olduğum bir şey değil. Bilgi için teşekkürler.
SmacL

11
std :: size_t genellikle (her zaman?) bir işaretçi boyutudur, tamsayı matematik biriminde yerel donanım desteğine sahip en büyük tamsayı boyutu değildir. Kullandığım her x86 işletim sisteminde, size_t, 32 bit işletim sistemi için 32 bit ve 64 bit işletim sistemi için 64 bittir.
Bay Fooz

2
Anladığım kadarıyla, bir dizinin maksimum sınırı , işlemci sözcüğünün maksimum değeri . Bunun nedeni dizin oluşturma operatörüdür. Örneğin, bir makinenin kelime boyutu 16 bit, ancak 32 bit adresleme yazmacı olabilir. Bir bellek hafızası, newveya parametresine iletilen parametre ile sınırlıdır malloc. İşaretçiden bir diziden daha büyük bir belleğe erişilebilir.
Thomas Matthews

171

Hiç kimse yığın çerçevesinin boyutundan bahsetmedi .

Belleğin ayrılabileceği iki yer vardır:

  • Öbek üzerinde (dinamik olarak ayrılmış bellek).
    Buradaki boyut sınırı, kullanılabilir donanımın ve işletim sisteminin kullanılmayan verileri geçici olarak depolamak için diğer aygıtları kullanarak alanı simüle etme yeteneğinin birleşimidir ( ör. Sayfaları sabit diske taşımak).
  • Yığında (Yerel olarak bildirilen değişkenler).
    Buradaki boyut sınırı derleyici tarafından tanımlanmıştır (olası donanım sınırları ile). Derleyici belgelerini okursanız, genellikle bu boyutu değiştirebilirsiniz.

Böylece bir diziyi dinamik olarak ayırırsanız (sınır büyüktür ve diğer gönderiler tarafından ayrıntılı olarak açıklanır.

int* a1 = new int[SIZE];  // SIZE limited only by OS/Hardware

Alternatif olarak dizi yığına tahsis edilirse, yığın çerçevesinin boyutu ile sınırlandırılırsınız. NB vektörleri ve diğer kaplar yığın içinde küçük bir mevcudiyete sahiptir, ancak genellikle verinin büyük kısmı yığın üzerinde olacaktır.

int a2[SIZE]; // SIZE limited by COMPILER to the size of the stack frame

4
Büyük dizilerin tercih edilen tahsisi bir yığında veya küresel olarak tanımlanmış değil, dinamik ayırma ( newveya aracılığıyla malloc) yoluyla yapılır .
Thomas Matthews

1
@Thomas Matthews: Benim dünyamda değil. Dinamik olarak atanan nesneler yönetim gerektirir. Dinamik olarak tahsis edilmesi gerekiyorsa, dinamik olarak tahsis edilmiş anıları temsil eden bir yığın nesnesini kullanırdım, std :: vector gibi.
Martin York

2
Orada eksik bir cornor durumdur: Global Arraysbir güzellik ve en iyi kaçınılması, bu kısıtlamaları kapsamına girmeyen ederken, stackve ihtiyacınız yok malloc/ freeonlarla çalışma yapmak.
ted

1
@ted, neden küresel diziler "en iyi kaçınılmalıdır"? Daha kesin olmak gerekirse, statik olarak ayrılmış diziler demek istediğinizi düşünüyorum. Kapsamlarının küresel olması gerekmez. Dinamik dizilerden daha iyi olduklarını iddia ediyorum çünkü dinamik olarak ayrılmış dizilerle yapamayacağınız onlarla (en azından Linux'ta) mutlak adresleme kullanabilirsiniz.
Z bozonu

2
Çok önemli bir nokta. Kısa süre önce, yapılandırılabilir bir maksimum arabellek boyutu sağlayan "üretim kalitesinde" açık kaynaklı bir proje ile karşılaştım. Tüm tamponlar yığına tahsis edildiğinden, yeterince büyük bir değerin yapılandırılması, programın başlatma sırasında hemen segfault olmasına neden olur.
aroth

13

Teorik bir bakış açısından değil, 32 bit Windows sisteminde, tek bir işlem için kullanılabilir maksimum toplam bellek miktarı 2 GB'dir. Çok daha fazla fiziksel belleğe sahip 64 bit işletim sistemine giderek sınırı aşabilirsiniz, ancak bunu yapmanın veya alternatiflerin aranması, amaçladığınız kullanıcılara ve bütçelerine bağlıdır. PAE kullanarak da biraz uzatabilirsiniz .

Dizinin türü çok önemlidir, çünkü birçok derleyicideki varsayılan yapı hizalaması 8 bayttır, bu da bellek kullanımı bir sorunsa çok israftır. Windows'u hedeflemek için Visual C ++ kullanıyorsanız, bunun üstesinden gelmek için #pragma pack yönergesine bakın.

Yapılması gereken başka bir şey, seyrek matrisler, sinek sıkıştırması, vb. Gibi bellek sıkıştırma tekniklerinde size yardımcı olabilecek şeylere bakmaktır. Dizinizi gerçekte dizilerinizde ne olduğu hakkında daha fazla bilgi vermek üzere düzenlerseniz, daha yararlı yanıtlar alabilirsiniz.

Düzenleme: Tam gereksinimleriniz hakkında biraz daha bilgi verildiğinde, depolama alanınızın 7.6 GB ile 76 GB arasında sıkıştırılmamış gibi görünmesi gerekir, bu da C ++ 'da bellekte bir dizi olarak saklamak için oldukça pahalı bir 64 bit kutu gerektirir. Verilerin neden erişim hızını varsaydığı ve rasgele erişime izin verdiği bellekte saklamak istediğiniz sorusunu gündeme getirir. Bu verileri bir dizinin dışında saklamanın en iyi yolu, ona nasıl erişmek istediğinize bağlıdır. Dizi üyelerine rasgele erişmeniz gerekiyorsa, çoğu uygulama için aynı anda erişilme eğilimi gösteren veri kümelerini gruplandırma yolları vardır. Örneğin, büyük CBS ve uzamsal veritabanlarında, veriler genellikle coğrafi alana göre döşenir. C ++ programlama terimlerinde, verilerinizin bölümlerini gerektiği gibi harici depolama biriminden almak için [] dizi operatörünü geçersiz kılabilirsiniz.


1
Program alanı dışında bellek tahsisine izin veren sistem çağrıları vardır; ancak bu işletim sistemine bağlıdır ve taşınabilir değildir. Bunları gömülü sistemlerde kullandık.
Thomas Matthews

4

Yukarıdakileri kabul ediyorum, eğer dizinizi intialize ediyorsanız

 int myArray[SIZE] 

SIZE bir tamsayı boyutu ile sınırlıdır. Ancak her zaman bir bellek yığınını ayırabilir ve bir işaretçi olabilir, malloc NULL döndürmediği sürece istediğiniz kadar büyük olabilir.


Bunun yanlış olup olmadığından emin değilim, yoksa sizi veya başka bir şeyi yanlış anladım. Örneğin, bu MSVC17 derleyicisi tarafından engellenir: Üretir int oops[INT_MAX]{0};,C2148 - total size of array must not exceed 0x7fffffff bytes
kayleeFrye_onDeck

16 GB DDR4 ve 66%şu anda uygulamamı VS2017 ile Windows 10'da hata ayıklama olarak başlatmadan önce kullanılan bellekle, başlangıçta ne kadar büyük bir int-dizisinin başlayabileceği konusunda tanımlanmamış bir sınırım var 0. Bazen ~ 257k elemanları ile yapabilirim, bazen bir yığın taşması elde ederim. Ben eklerseniz şey ana ve dizinin yanı sıra Uygulamama bu sayı (besbelli) iner. Bu sayıyı belirlemek için denemek zorunda kaldım, bu yüzden bu metriğin bir boşluktaki teorik sınırlarınızı bilmenin ötesine nasıl güvenilebileceğini görmüyorum.
kayleeFrye_onDeck

4

Yanıtları özetlemek, genişletmek ve sorunuzu doğrudan yanıtlamak için:

Hayır, C ++ bir dizinin boyutları için herhangi bir sınır koymaz .

Ancak dizinin bellekte bir yerde saklanması gerektiğinden, bilgisayar sisteminin diğer bölümleri tarafından uygulanan bellekle ilgili sınırlar geçerlidir. Bu sınırların doğrudan dizinin boyutları (= öğe sayısı) ile değil, boyutu (= alınan bellek miktarı) ile ilgili olduğunu unutmayın. Boyutlar ( D ) ve bellek boyutu ( S tek bir eleman (alınan bellek ile ilgili olarak bir dizi), aynı değildir e ): S = D * e . E

şimdi şunlara bağlıdır:

  • dizi öğelerinin türü (öğeler daha küçük veya daha büyük olabilir)
  • bellek hizalaması (performansı artırmak için, öğeler arasında bir değerin çarpanları olan ve
    öğeler arasında 'boşa alan' (dolgu) oluşturan adreslere yerleştirilir
  • nesnelerin statik parçalarının boyutu (nesneye yönelik programlamada, aynı türdeki nesnelerin statik bileşenleri, aynı türdeki nesnelerin sayısından bağımsız olarak yalnızca bir kez saklanır)

Ayrıca, dizi verilerini yığın (otomatik değişken: olarak int t[N]) veya yığın ( STL mekanizmalarıyla malloc()/ newveya kullanarak dinamik konumlandırma ) veya işlem belleğinin statik olarak (gibi) ayırarak bellekle ilgili farklı sınırlamalar aldığınızı unutmayın. statik bir değişken:) static int t[N]. Yığına ayrılırken bile, yığınla ayrılan bellek bloklarına referansları saklamak için yığın üzerinde çok az miktarda belleğe ihtiyacınız vardır (ancak bu genellikle ihmal edilebilir).

Türün boyutu size_t, programcı üzerinde hiçbir etkiye sahip değildir (programcı size_t, bunun için tasarlandığı gibi dizinleme için tür kullandığını varsayar ), derleyici sağlayıcısının yaptığı gibi Bellek boyutu sınırlamalarının kaynaklarıtypedef verilen platform için mümkün olan maksimum bellek miktarını ele alacak kadar büyük bir tamsayı türüne mimari.

  • işlem için kullanılabilir bellek miktarı (32 bit uygulamalar için 64 bitlik işletim sistemlerinde bile 2 ^ 32 bayt ile sınırlıdır),
  • işlem belleğinin bölünmesi (örneğin, yığın veya yığın için tasarlanmış işlem belleğinin miktarı),
  • fiziksel belleğin parçalanması (birçok dağınık küçük boş bellek parçası bir monolitik yapının depolanması için geçerli değildir),
  • fiziksel bellek miktarı,
  • ve sanal bellek miktarı.

Uygulama düzeyinde 'ayarlanamazlar, ancak farklı bir derleyici (yığın boyutu sınırlarını değiştirmek için) kullanmakta veya uygulamanızı 64 bit olarak taşıyabilir veya başka bir işletim sistemine bağlayabilir veya fiziksel / (sanal? fiziksel?) makinenin sanal bellek yapılandırması.

Yukarıdaki tüm faktörleri dışsal bozukluklar ve dolayısıyla çalışma zamanı hatalarının olası kaynakları olarak ele almak ve program kodunuzdaki bellek ayırma ile ilgili hataları dikkatlice kontrol etmek ve bunlara tepki vermek nadir değildir (ve hatta tavsiye edilmez).

Son olarak: C ++ herhangi bir sınır koymazken, kodunuzu çalıştırırken bellekle ilgili olumsuz durumları kontrol etmeniz gerekir ... :-)


3

Birçok mükemmel yanıt belirtildiği gibi, C ++ derleyici sürümünüze, işletim sistemine ve bilgisayar özelliklerine bağlı olan birçok sınırlama vardır. Ancak, Python'da makinenizdeki sınırı kontrol eden aşağıdaki komut dosyasını öneririm.

İkili arama kullanır ve her yinelemede, boyutun bir dizisini oluşturmaya çalışan bir kod oluşturarak orta boyutun mümkün olup olmadığını kontrol eder. Komut dosyası derlemeye çalışır (özür dilerim, bu bölüm yalnızca Linux'ta çalışır) ve başarıyı bağlı olarak ikili aramayı ayarlar. Bunu kontrol et:

import os

cpp_source = 'int a[{}]; int main() {{ return 0; }}'

def check_if_array_size_compiles(size):
        #  Write to file 1.cpp
        f = open(name='1.cpp', mode='w')
        f.write(cpp_source.format(m))
        f.close()
        #  Attempt to compile
        os.system('g++ 1.cpp 2> errors')
        #  Read the errors files
        errors = open('errors', 'r').read()
        #  Return if there is no errors
        return len(errors) == 0

#  Make a binary search. Try to create array with size m and
#  adjust the r and l border depending on wheather we succeeded
#  or not
l = 0
r = 10 ** 50
while r - l > 1:
        m = (r + l) // 2
        if check_if_array_size_compiles(m):
                l = m
        else:
                r = m

answer = l + check_if_array_size_compiles(r)
print '{} is the maximum avaliable length'.format(answer)

Makinenize kaydedip başlatabilirsiniz ve oluşturabileceğiniz maksimum boyutu yazdırabilirsiniz. Makinem için 2305843009213693951.


2

Düşündüğüm bir şey, önceki cevaplarda belirtildi.

İnsanlar tasarımlarında böyle şeyler kullandıklarında her zaman yeniden düzenleme anlamında "kötü bir koku" hissederim.

Bu çok büyük bir dizi ve muhtemelen verilerinizi hem verimlilik açısından hem de performans açısından temsil etmenin en iyi yolu değil.

şerefe,

soymak


Ne kullanmam gerektiğine dair bir öneriniz var mı?
luiss

Bize veriyi ne sakladığınızı söyleyebilirseniz, belki de yapabiliriz. (-:
Rob Wells

Üzgünüm Luis ilk cevabım çok huysuzdu. Verilerinizin niteliği tarafından yönlendirilecektir. Verilerinizin ilişkileri, verileri temsil etmek için kullandığınız modeli yönlendirecektir. O zaman koleksiyon bundan belli olmalı . Değilse, veri modeli hakkında endişelenirim.
Rob Wells

benim için o kadar da kötü değil: böyle bir oyuncakla önbelleğe alınmış bir veritabanına ne dersin? tweaktown.com/news/22066/…

2

Bu kadar büyük verilerle uğraşmanız gerekiyorsa, bunları yönetilebilir parçalara ayırmanız gerekir. Hepsi küçük bilgisayarlarda belleğe sığmaz. Muhtemelen verilerin bir kısmını diskten yükleyebilir (makul olarak ne olursa olsun), hesaplamalarınızı ve değişikliklerinizi yapabilir, diske kaydedebilir ve tamamlanana kadar tekrarlayabilirsiniz.


Ayrıca, belleğe sığmayacak kadar büyük verileri işlemek için örnek algoritmada Birleştirme Sıralaması konusuna bakın.
Thomas Matthews

2

Tüm mevcut cevaplar kadar sinir bozucu olmayan spesifik olmayanlar, çoğunlukla haklıdırlar, ancak her zaman belirtilmeyen birçok uyarıyla birlikte. Asıl önemli olan, iki üst sınırınız var ve bunlardan sadece biri aslında tanımlanmış bir şey, bu yüzden YMMV :

1. Derleme zamanı sınırları

Temel olarak, derleyicinizin neye izin vereceğini. X64 Windows 10 kutusundaki Visual C ++ 2017 için, bu 2GB sınırına girmeden önce derleme sırasındaki maksimum sınırımdır,

unsigned __int64 max_ints[255999996]{0};

Bunu ben yapsaydım,

unsigned __int64 max_ints[255999997]{0};

Ben alırım:

Error C1126 automatic allocation exceeds 2G

2G'nin 255999996/ ile nasıl ilişkilendirildiğinden emin değilim 7. Her iki sayıyı da araştırdım ve bulabileceğim tek şey bu * nix Q&A ile ilgili hassas bir konuydudc . Her iki durumda da, hangi int int türünü doldurmaya çalıştığınız önemli değil, sadece kaç öğe tahsis edilebilir.

2. Çalışma zamanı sınırları

Yığınızın ve yığının kendi sınırlamaları vardır. Bu sınırlar hem mevcut sistem kaynaklarına göre değişen değerlerin yanı sıra uygulamanızın ne kadar "ağır" olduğudur. Örneğin, mevcut sistem kaynaklarımla, bunu çalıştırmak için alabilirim:

int main()
{
    int max_ints[257400]{ 0 };
    return 0;
}

Ama eğer biraz değiştirirsem ...

int main()
{
    int max_ints[257500]{ 0 };
    return 0;
}

Bam! Yığın taşması!

Exception thrown at 0x00007FF7DC6B1B38 in memchk.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x000000AA8DE03000). Unhandled exception at 0x00007FF7DC6B1B38 in memchk.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x000000AA8DE03000).

Ve sadece uygulama noktanızın tüm ağırlığını ayrıntılandırmak için, bu iyi oldu:

int main()
{
    int maxish_ints[257000]{ 0 };
    int more_ints[400]{ 0 };
    return 0;
}  

Ancak bu bir yığın taşmasına neden oldu:

int main()
{
    int maxish_ints[257000]{ 0 };
    int more_ints[500]{ 0 };
    return 0;
}  

1

Std :: vector max_size () üye işlevi burada belirtilmedi şaşırdım .

"Kabın sistem veya kitaplık uygulama sınırlamaları nedeniyle tutabileceği maksimum öğe sayısını, yani en büyük kapsayıcı için std :: distance (begin (), end ()) döndürür."

Bunun std::vectorkaputun altında dinamik bir dizi olarak uygulandığını biliyoruz , bu nedenle makinenizdeki dinamik bir dizinin max_size()maksimum uzunluğuna çok yakın bir yaklaşım vermelidir .

Aşağıdaki program, çeşitli veri türleri için yaklaşık maksimum dizi uzunluğuna sahip bir tablo oluşturur.

#include <iostream>
#include <vector>
#include <string>
#include <limits>

template <typename T>
std::string mx(T e) {
    std::vector<T> v;
    return std::to_string(v.max_size());
}

std::size_t maxColWidth(std::vector<std::string> v) {
    std::size_t maxWidth = 0;

    for (const auto &s: v)
        if (s.length() > maxWidth)
            maxWidth = s.length();

    // Add 2 for space on each side
    return maxWidth + 2;
}

constexpr long double maxStdSize_t = std::numeric_limits<std::size_t>::max();

// cs stands for compared to std::size_t
template <typename T>
std::string cs(T e) {
    std::vector<T> v;
    long double maxSize = v.max_size();
    long double quotient = maxStdSize_t / maxSize;
    return std::to_string(quotient);
}

int main() {
    bool v0 = 0;
    char v1 = 0;

    int8_t v2 = 0;
    int16_t v3 = 0;
    int32_t v4 = 0;
    int64_t v5 = 0;

    uint8_t v6 = 0;
    uint16_t v7 = 0;
    uint32_t v8 = 0;
    uint64_t v9 = 0;

    std::size_t v10 = 0;
    double v11 = 0;
    long double v12 = 0;

    std::vector<std::string> types = {"data types", "bool", "char", "int8_t", "int16_t",
                                      "int32_t", "int64_t", "uint8_t", "uint16_t",
                                      "uint32_t", "uint64_t", "size_t", "double",
                                      "long double"};

    std::vector<std::string> sizes = {"approx max array length", mx(v0), mx(v1), mx(v2),
                                      mx(v3), mx(v4), mx(v5), mx(v6), mx(v7), mx(v8),
                                      mx(v9), mx(v10), mx(v11), mx(v12)};

    std::vector<std::string> quotients = {"max std::size_t / max array size", cs(v0),
                                          cs(v1), cs(v2), cs(v3), cs(v4), cs(v5), cs(v6),
                                          cs(v7), cs(v8), cs(v9), cs(v10), cs(v11), cs(v12)};

    std::size_t max1 = maxColWidth(types);
    std::size_t max2 = maxColWidth(sizes);
    std::size_t max3 = maxColWidth(quotients);

    for (std::size_t i = 0; i < types.size(); ++i) {
        while (types[i].length() < (max1 - 1)) {
            types[i] = " " + types[i];
        }

        types[i] += " ";

        for  (int j = 0; sizes[i].length() < max2; ++j)
            sizes[i] = (j % 2 == 0) ? " " + sizes[i] : sizes[i] + " ";

        for  (int j = 0; quotients[i].length() < max3; ++j)
            quotients[i] = (j % 2 == 0) ? " " + quotients[i] : quotients[i] + " ";

        std::cout << "|" << types[i] << "|" << sizes[i] << "|" << quotients[i] << "|\n";
    }

    std::cout << std::endl;

    std::cout << "N.B. max std::size_t is: " <<
        std::numeric_limits<std::size_t>::max() << std::endl;

    return 0;
}

MacOS'umda (clang sürüm 5.0.1) aşağıdakileri alıyorum:

|  data types | approx max array length | max std::size_t / max array size |
|        bool |   9223372036854775807   |             2.000000             |
|        char |   9223372036854775807   |             2.000000             |
|      int8_t |   9223372036854775807   |             2.000000             |
|     int16_t |   9223372036854775807   |             2.000000             |
|     int32_t |   4611686018427387903   |             4.000000             |
|     int64_t |   2305843009213693951   |             8.000000             |
|     uint8_t |   9223372036854775807   |             2.000000             |
|    uint16_t |   9223372036854775807   |             2.000000             |
|    uint32_t |   4611686018427387903   |             4.000000             |
|    uint64_t |   2305843009213693951   |             8.000000             |
|      size_t |   2305843009213693951   |             8.000000             |
|      double |   2305843009213693951   |             8.000000             |
| long double |   1152921504606846975   |             16.000000            |

N.B. max std::size_t is: 18446744073709551615

Açık ideone gcc 8.3 alıyorum:

|  data types | approx max array length | max std::size_t / max array size |
|        bool |   9223372036854775744   |             2.000000             |
|        char |   18446744073709551615  |             1.000000             |
|      int8_t |   18446744073709551615  |             1.000000             |
|     int16_t |   9223372036854775807   |             2.000000             |
|     int32_t |   4611686018427387903   |             4.000000             |
|     int64_t |   2305843009213693951   |             8.000000             |
|     uint8_t |   18446744073709551615  |             1.000000             |
|    uint16_t |   9223372036854775807   |             2.000000             |
|    uint32_t |   4611686018427387903   |             4.000000             |
|    uint64_t |   2305843009213693951   |             8.000000             |
|      size_t |   2305843009213693951   |             8.000000             |
|      double |   2305843009213693951   |             8.000000             |
| long double |   1152921504606846975   |             16.000000            |

N.B. max std::size_t is: 18446744073709551615

Bunun teorik bir sınır olduğu ve çoğu bilgisayarda bu sınıra ulaşmadan çok fazla bellek kalmayacağına dikkat edilmelidir. Örneğin, tip görüyoruz charüzerinde gcc, öğelerin sayısı max eşittir std::size_t. Bunu denemekle hatayı alırız:

prog.cpp: In function int main()’:
prog.cpp:5:61: error: size of array is too large
  char* a1 = new char[std::numeric_limits<std::size_t>::max()];

Son olarak, @MartinYork'un belirttiği gibi, statik diziler için maksimum boyut yığınınızın boyutu ile sınırlıdır.


0

Daha önce de belirtildiği gibi, dizi boyutu donanımınız ve işletim sisteminiz (man ulimit) ile sınırlıdır. Ancak yazılımınız yalnızca yaratıcılığınızla sınırlı olabilir. Örneğin, "dizinizi" diskte saklayabilir misiniz? Gerçekten uzun uzun intsa ihtiyacınız var mı? Gerçekten yoğun bir diziye mi ihtiyacınız var? Hatta bir diziye bile ihtiyacınız var mı?

Basit bir çözüm 64 bit Linux kullanmak olacaktır. Diziniz için fiziksel olarak yeterli koza sahip olmasanız bile, işletim sisteminiz, işleminiz için kullanılabilir sanal bellek muhtemelen fiziksel bellekten çok daha büyük olduğu için belleği ayırmanıza izin verecektir. Gerçekten dizideki her şeye erişmeniz gerekiyorsa, bu onu diskte saklamak demektir. Erişim kalıplarınıza bağlı olarak, bunu yapmanın daha etkili yolları olabilir (örneğin: mmap () kullanmak veya verileri bir dosyada sırayla depolamak (bu durumda 32 bit Linux yeterli olacaktır)).


2
Hmm, diskler, diziler, ... sanal bellek duyan herkes . Sanal belleği destekleyen işletim sistemleri, sabit disk gibi bellek için harici bir aygıt kullanmaya başlar ve dahili bellekli parçaları çıkarır.
Thomas Matthews

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.