首頁  >  問答  >  主體

在C/C++中数组长度的最大值是多少,跟哪些因素有关系?

PHP中文网PHP中文网2713 天前1032

全部回覆(4)我來回復

  • PHP中文网

    PHP中文网2017-04-17 14:57:49

    經過了好長時間,我才勉強總結了一個答案。

    • 首先,如果要確定一個陣列的最大長度,我們需要知道它的資料類型,因此,陣列的資料類型是其中一個限制因素。因為不同資料類型的元素大小不同。很明顯(我們假設int為4字節,char為1位元組),資料型別為char的陣列的最大長度是型別為int的陣列的4倍。

    • 另外,我們不難想到,大小(size)的資料類型,也就是陣列下標的資料類型,其實也是限制因素。在C/C++中,數組下標的類型是std::size_t,因此數組的大小首先不能超過size_t所能表示的大小。這個資料類型是在庫檔案stdio.h中透過typedef聲明的,對於32位元程式它被定義為unsighed int,對於64位元程式定義為unsigned long。前者能表示的最大大小為2^32-1,後者為2^64-1。

    • 然後,我又想到了實體記憶體的大小。這一點不用細說,因為程式運行時一旦超過實體記憶體的大小,這個程式就會立刻崩潰。

    上面幾點都是比較籠統的限制,我們換一個高大上的表達-宏觀上的限制因素。下面,我們介紹幾個微觀上的限制因素

    • 大家應該都知道,陣列的分配方式大概有兩種方式:靜態分配動態分配。再具體點兒的話,根據數組宣告的位置,我們可以將數組分為局部數組全域數組。這樣討論的話,就複雜了,我們暫時可以將數組分為四類(只是筆者本人這樣劃分,不知道官方是否有這樣的分類):靜態分配的局部陣列、動態分配的局部陣列、靜態分配的全域陣列、動態分配的全域陣列。

      • 第一種陣列分配時,使用的是堆疊上的空間,因此靜態分配得到的局部陣列的大小受限於堆疊的大小。具體來說就是數組所在函數棧幀的大小,當然堆疊幀的大小肯定不能超過堆疊的大小。如果你對編譯器的使用比較熟悉或你有閱讀過編譯器文件的話,你應該知道如何調整堆疊幀的大小限制。在WINDOWS下,棧的大小是2M(也有的說是1M,總之是一個編譯時就確定的常數),如果申請的空間超過棧的剩餘空間時,將會提示溢位。

      • 對於第二種數組和第四種數組,我覺得應該要分成一個類別。本質上它們都是在堆上分配空間,因此它們的大小受限於堆的大小。堆是不連續的內存區域,堆的大小受限於電腦系統中有效的虛擬內存,因此堆的大小一般都比較大。

      • 至於第三種數組,我們知道它是在靜態儲存區分配記憶體空間,因此大小自然受限於靜態儲存區的大小,也叫做BSS(Block Started by Symbol),在彙編語言中,我麼也稱之為資料段。目前我還不太清楚靜態儲存區的大小限制,我在我的電腦(Core i3-3110M, 內存8GB)上做過實驗發現我所能分配的最大大小大約為剩餘內存的1/2。網路上有這樣說的:“你的常量有多大就多大”,但是還有待考證。

    Note:關於堆疊幀的概念可以參考《深入理解電腦系統》這本書,或是其他關於電腦體系結構的資料。

    已經整理成部落格:C++中陣列的最大長度。

    回覆
    0
  • 天蓬老师

    天蓬老师2017-04-17 14:57:49

    如果是堆疊上的數組,大小受限於堆疊大小(記得是4MB)。如果是堆的話,就比較大了,理論上可以使用作業系統允許進程使用的最大內存,減去內存中的程式碼、常數等佔用的空間。不過非要全部用上,那麼程式離崩潰也就不遠了。

    回覆
    0
  • PHP中文网

    PHP中文网2017-04-17 14:57:49

    和 cpu 的尋址位寬相關,以及和 作業系統 的尋址模式相關

    在虛擬記憶體的平坦尋址模式下

    32位元的指標定址範圍是 2^32 = 4GB

    回覆
    0
  • ringa_lee

    ringa_lee2017-04-17 14:57:49

    陣列可以分別開在堆疊、堆疊、靜態儲存區,看你的需要、CPU的支援程度和作業系統的限制。

    回覆
    0
  • 取消回覆