最近用c刷pat演算法題目, 發現c語言有太多需要關注大小範圍的東西必須
知道, 雖說挺麻煩, 但也挺有意思.
首先就是int
型別的取值範圍, 這個太常用. c語言標準規定最低範圍是
[-2^16 + 1, 2^16], 即[-65535, 65536], 但這個明顯已經過時, 目前
絕大部分機器支援的int
範圍是[-2^32 + 1, 2^32], 也就是正負20個億
左右, 因此大家刷題的時候只要整數範圍是在20億這個量級, 就可以大膽的
使用int
, 不必動用long int
,long long int
等. 更多關於c語言
自帶資料型別極限, 以及在自己本地測試資料型別極限, 可以訪問
這裡如果我們直接在c程式main函式中開個1000萬的整型陣列, 執行這個程式會發生
什麼 ?
#include int main()
在win10_64位 codeblock 16.01下執行結果:
在win10_64位 gcc6.3.0(mingw)命令列編譯執行結果:
可以看到, 在ide中執行程式直接崩潰, 在命令列中什麼也沒輸出,
總之就是程式執行不正常, 可以理解為記憶體爆掉了. 難道c語言連
1000萬的整型陣列都開不出來嗎?
舉個例子:若果大家經常刷演算法題應該有這個經驗很多時候用乙個
非常大的陣列解題會顯著提高效率, 非常方便. 比如輸入100萬
個數, 每個數都不大於10萬, 然後任意給你乙個數, 問你這個數存
不存在, 也就是查詢, 若果按照傳統的方法就算用c語言自帶的2分
查詢法, 每次在100萬個資料中找出乙個數, 工作量依舊非常巨大,
而且效率低下, 而直接把輸入的資料當陣列下標開個10萬的陣列解決,
問題則非常簡單. 說到這裡相信懂的人已經懂了, 如果不知所云也沒
關係, 繼續刷題, 以後回過頭來看.
大家可能都能聽過什麼棧記憶體, 堆記憶體, 什麼堆疊, 靜態記憶體, 動態記憶體
等等, 一些概念, 乍一看一臉懵逼, 這些都什麼玩意, 我們現在先不關注
概念的東西, 直接看實際需求.
上面我們已經提到, 在main函式中開個1000萬的整型, 程式就爆掉了, 那
到底, 最大能開多大的容量的整型陣列, 才能不爆掉呢. 首先我們先來一波
計算, 大部分機器sizeof(int)
得到的值是4, 也就是乙個整型資料
需要4個位元組的容量, 1000萬個整型陣列需要4 * 10000000 / 1024 / 1024
,
計算結果大約是38m
1g = 1024m, 1m = 1024k, 1k = 1024byte(位元組)在linux或者是在windows下的mingw環境下, 可以輸入命令
ulimit -a
, 檢視
c語言記憶體分配情況, 在下圖我的機器上可以看到stack size
大約為2m
按照乙個整型資料佔4個位元組來算, 2m記憶體用來開陣列, 最大也就開個52萬左右,
我們的測試開了1000萬, 顯然是要爆掉的. 那麼問題來了, 難道我們的c語言,
就tm只能提供區區50來萬的陣列空間嗎? 別說50萬, 就是1千萬, 也不一定完全
夠用呀. 當然不是, 上面只是c語言分配記憶體的預設方法, 也是最簡單的方法,
這種方法用的是棧記憶體, 而c語言能提供的棧記憶體非常有限, 頂天就那麼幾m,
如果需要拿到更大的記憶體空間, 就不能使用這種方法了.
若果大家覺得52萬, 貌似已經夠自己用了, 我只能說, 兄弟再刷兩題看看第1種方法: 使用棧和堆疊意思一樣, 堆是另一種資料結構
malloc
這種方法我在這裡不展開細說了, 如果大家對malloc
很熟的話, 我這麼
一提大家應該就明白了. 最簡單的用法就是用malloc分配陣列空間
#include #include int main()
第2種方法: 把變數宣告放到檔案作用域中(或者叫全域性作用域)
這種方法重點推薦使用, 簡單粗暴非常方便, 什麼叫檔案作用域就是把
變數宣告挪到所有函式之外, 也就是main函式的上面即可. 源**幾乎
不用作任何改動, 直接把大資料變數宣告搬到main函式上面即可.
#include #define len 24
long long int arr[1 << len]; // 宣告放到這裡就對啦
int main()
return 0;
}
1 << 24
相當於1000000000000000000000000(24個0), 也就是2^24 = 16777216
下面是我機器的執行結果, 注意執行時間可能會非常長
可以看到, 即便是開出1600萬, 這麼大的陣列, 程式依舊能夠正常執行.
c語言的記憶體分配模式大致分為3種
自動分配. 也就是寫在main函式或其它函式裡面的, 使用的是棧記憶體,
一般棧記憶體只有幾m, 所以這種方法, 分配的整型陣列空間可能只有
幾十萬, 一般建議刷演算法題的時候, 超過10萬就不用這種方法
使用malloc分配, 可以分配的很大, 一般是幾個g
把宣告放在全域性作用域中, 可以分配的很大, 一般是幾個g
【c語言程式設計】五大記憶體分割槽
warning: left shift count >= width of type
**c語言申請記憶體時堆疊大小限制
c primee plus 第6版 中文版 2016.4出版 stephen prata著 姜佑譯
C語言的記憶體分配
文章一 c語言的記憶體分配模型 1 程式 區 存放函式體的二進位制 2 全域性區資料區 全域性資料區劃分為三個區域。全域性變數和靜態變數的儲存是放在一塊的,初始化的全域性變數和靜態變數在一塊區域,未初始化的全域性變數和未初始化的靜態變數在相鄰的另一塊區域。常量資料存放在另乙個區域裡。這些資料在程式結...
C語言記憶體分配
c語言的記憶體分配主要有5個區域 1 棧區 在執行函式時,函式內的區域性變數 不包括static變數 函式返回值的儲存單元在棧區上建立。函式執行結束時這些儲存單元自動被釋放。棧區記憶體分配運算內置於處理器的指令集中,效率很高,但分配的記憶體容量有限。2 堆區 程式在執行的時候用malloc call...
C語言記憶體分配
c語言的記憶體分配主要有5個區域 1 棧區 在執行函式時,函式內的區域性變數 不包括static變數 函式返回值的儲存單元在棧區上建立。函式執行結束時這些儲存單元自動被釋放。棧區記憶體分配運算內置於處理器的指令集中,效率很高,但分配的記憶體容量有限。2 堆區 程式在執行的時候用malloc call...