C++中數組的最大長度

最近寫程序的時候,突然想到了這個問題:在C++中數組的長度有限制嗎?我覺得肯定是有的,但限制是多少呢?經過了好長時間,我才勉強總結了一個答案。

宏觀上的限制因素

  • 首先,如果要確定一個數組的最大長度,我們需要知道它的數據類型,因此,數組的數據類型是其中一個限制因素。因爲不同數據類型的元素大小不同。很顯然(我們假設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:關於棧幀的概念可以參考《深入理解計算機系統》這本書,或者其他關於計算機體系結構的資料。

參考資料

知識共享許可協議
本作品採用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章