這個問題是我最近遇到的乙個問題,這裡寫成部落格記錄下來.剛學計算機系統不就,如果有**不對的地方請指正。
**內容是下面這個樣子的
main.c
#include"stdio.h"
int a = 100,b = 200;
int main()
func.c
double a;
void func()
注意上面兩個**片是在同乙個工程下兩個不同c語言檔案中的,因為在同乙個c檔案下宣告兩個同名變數編譯器會報錯,而且a,b都是全域性變數。
執行結果如下圖所示:
我們發現最後列印的資料有點出乎我們的意料,而且重複執行多次,發現結果都是一樣的,說明第二個數不是乙個隨機數,接下來我們解釋一下為什麼列印這兩個數。
從上圖可以看到a和b的位址是連續的,說明a,b的記憶體是連續申請的,接下來我們再檢視一下a,b的記憶體:
上圖框起來的兩組資料即為a和b的16進製表示,由於膝上型電腦是小端機,所以讀的時候應該從右往左讀,即a在記憶體中表示為00 00 00 64,b在記憶體中表示為00 00 00 c8,換算成10進製恰好為100和200。
繼續往下除錯:
當程式執行到a = 1.0這個語句的時候,可以看到a的位址沒有變,但是a的型別已經變成了double的型別,但是我們都知道,int型的變數是32位的,但是double是64位的。很明顯,程式剛剛申請的4個位元組的是存不下的,然後程式怎麼處理這種情況呢?我們檢視一下a的記憶體:
我們可以看到,a和b的記憶體都發生了改變,讀出其中的16進製制數為3f f0 00 00 00 00 00 00,計算一下會發現這個數恰恰對應雙精度浮點數1.0。這說明剛剛在a從int型變為double型別的時候,由於double型的資料需要64位來進行儲存,所以程式就在原來32位的基礎上,有連續的申請了4個位元組的記憶體,由此由8個位元組來存1.0這個雙精度浮點型這個資料。但是a後面的32位是屬於b的,所以這個1.0就占用的b的記憶體,但是b的位址又沒有改變,所以b的指標還是指在原來的地方。最後我們格式化輸出的是兩個%d型別的資料,所以64位的記憶體又會分成兩個32位的重新分給a和b。即現在a的16進製表示為00 00 00 00,b的16進製表示為3f f0 00 00。a轉換成10進製肯定是0,我們用計算器算一下b轉換成10進製後是多少:
可以看到,和程式輸出的結果是一樣的。
總結:
當我們連續申請兩個全域性變數的時候,那麼他們的記憶體也是連續的,當我們改變第乙個變數的資料型別的時候,如果原來申請的記憶體的大小不夠用來儲存新的資料型別,那麼程式就會在原來記憶體的基礎上,緊接著原來的記憶體向後申請直到可以存下新的資料型別的資料。由於在最開始的時候兩個變數是連續申請的,這時候後面的資料的記憶體就會被前乙個資料占用,就造成了上面的程式出現的情況。
在這篇文章中提到了大端機、小端機,int型,double型別的表示以及計算,如果有不了解的可以看一下其他人的博文。還有就是為什麼申請的是全域性變數。在計算機中全域性變數和區域性變數是儲存的不同的記憶體中的,也就是所說的棧記憶體和堆記憶體,這篇文章也不做詳細介紹。
C 申請連續的物件記憶體
實在慚愧,想要申請指向乙個類的連續的批量的記憶體,盡然不知道怎麼申請 1 基本型別的申請 申請連續的10個指向int型別記憶體 int parray new int 10 2 結構體和類 class a private int x 申請10個連續的指向a物件的記憶體 pa new a 10 erro...
C 申請連續的物件記憶體
實在慚愧,想要申請指向乙個類的連續的批量的記憶體,盡然不知道怎麼申請 1 基本型別的申請 申請連續的10個指向int型別記憶體 int parray new int 10 2 結構體和類 class a private int x 申請10個連續的指向a物件的記憶體 pa new a 10 erro...
C語言動態記憶體申請分析
1 c語言中的一切操作都是基於記憶體的 2 變數和陣列都是記憶體的別名 1 記憶體分配由編譯器在編譯期間決定 2 定義陣列的時候必須指定陣列的長度 3 陣列的長度是在編譯期間就必須確定的 1 malloc和free用於執行動態記憶體分配和釋放 2 malloc所分配的是一塊連續的記憶體 3 mall...