1. 程式人生 > >C語言區域性變數在記憶體棧中的順序

C語言區域性變數在記憶體棧中的順序

首先總結規則,詳細分析見下面:
規則1:記憶體由低到高優先分配給佔位8位元組、4位元組、2位元組、1位元組的資料型別
資料型別佔位說明:
8位元組:double、longlong int
4位元組:int、float、long int、unsigned int
2位元組:short 、unsigned short
1位元組:char 、unsigned char
例如,分別定義下列變數,記憶體地址中由低到高分別為:
double < int < short < char
規則2:同總佔位的型別按定義變數的先後順序記憶體地址會增加


規則3:在規則2前提下,定義陣列不會和同總資料型別混佔記憶體
下面看示例程式:

示例程式1#include <stdio.h>

int main(int argc, const char *argv[])
{
    char char_a;
    short short_a;
    int int_a;
    float float_a;
    double double_a;
    unsigned int uint_a;
    long int lint_a;
    long long int dlint_a;

    printf("  &char_a : %p\n"
,&char_a); printf(" &short_a : %p\n",&short_a); printf(" &int_a : %p\n",&int_a); printf(" &float_a : %p\n",&float_a); printf("&double_a : %p\n",&double_a); printf(" &unsigned_int_a : %p\n",&uint_a); printf(" &long_int_a : %p\n"
,&lint_a); printf("&long_long_int_a : %p\n",&dlint_a); return 0; } 測試結果1: *不同機器顯示的記憶體地址會略有不同* &char_a : 0xbfa844af &short_a : 0xbfa844ac &int_a : 0xbfa8449c &float_a : 0xbfa844a0 &double_a : 0xbfa84488 &unsigned_int_a : 0xbfa844a4 &long_int_a : 0xbfa844a8 &long_long_int_a : 0xbfa84490

**分析:有結果可知變數下記憶體中的分佈為(從低地址到高地址,()中為它們所佔位元組):
double(8)、long long int(8)、int(4) 、float(4)、unsigned int(4)、long int(4)、short(2)、char(1)
這裡可以佐證規則1.**

示例程式2#include <stdio.h>

int main(int argc, const char *argv[])
{
    char char_a;
    short short_a;
    int int_a;
    float float_a;
    double double_a;
    unsigned int uint_a;
    long int lint_a;
    long long int dlint_a;
    char char_b;
    short short_b;
    int int_b;
    float float_b;
    double double_b;
    unsigned int uint_b;
    long int lint_b;
    long long int dlint_b;

    printf("  &char_a : %p\n",&char_a);
    printf("  &char_b : %p\n",&char_b);
    printf(" &short_a : %p\n",&short_a);
    printf(" &short_b : %p\n",&short_b);
    printf("   &int_a : %p\n",&int_a);
    printf("   &int_b : %p\n",&int_b);
    printf(" &float_a : %p\n",&float_a);
    printf(" &float_b : %p\n",&float_b);
    printf("&double_a : %p\n",&double_a);
    printf("&double_b : %p\n",&double_b);
    printf(" &unsigned_int_a : %p\n",&uint_a);
    printf(" &unsigned_int_b : %p\n",&uint_b);
    printf("     &long_int_a : %p\n",&lint_a);
    printf("     &long_int_b : %p\n",&lint_b);
    printf("&long_long_int_a : %p\n",&dlint_a);
    printf("&long_long_int_b : %p\n",&dlint_b);

    return 0;
}

測試結果2:
*不同機器顯示的記憶體地址會略有不同*
  &char_a : 0xbfde982e
  &char_b : 0xbfde982f
 &short_a : 0xbfde982a
 &short_b : 0xbfde982c
   &int_a : 0xbfde9808
   &int_b : 0xbfde9818
 &float_a : 0xbfde980c
 &float_b : 0xbfde981c
&double_a : 0xbfde97e8
&double_b : 0xbfde97f8
 &unsigned_int_a : 0xbfde9810
 &unsigned_int_b : 0xbfde9820
     &long_int_a : 0xbfde9814
     &long_int_b : 0xbfde9824
&long_long_int_a : 0xbfde97f0
&long_long_int_b : 0xbfde9800

分析:這裡由int的兩個變數a和b之間夾了float、unsigned int等變數,可以佐證規則2

測試案例3#include <stdio.h>

int main(int argc, const char *argv[])
{
    char char_b[4];
    int int_b[4]; 
    char char_a;
    short short_a;
    int int_a;

    printf("  &char_a : %p\n",&char_a);
    printf(" &short_a : %p\n",&short_a);
    printf("   &int_a : %p\n",&int_a);
    printf("   &int_b : %p\n",int_b);
    printf("  &char_b : %p\n",char_b);

    return 0;
}
測試結果3*不同機器顯示的記憶體地址會略有不同*
  &char_a : 0xbf8fdcc7
 &short_a : 0xbf8fdcc4
   &int_a : 0xbf8fdcc0
   &int_b : 0xbf8fdcb0
  &char_b : 0xbf8fdcc8
測試案例4#include <stdio.h>

int main(int argc, const char *argv[])
{
    char char_a;
    short short_a;
    int int_a;
    int int_b[4]; 
    char char_b[4];

    printf("  &char_a : %p\n",&char_a);
    printf(" &short_a : %p\n",&short_a);
    printf("   &int_a : %p\n",&int_a);
    printf("   &int_b : %p\n",int_b);
    printf("  &char_b : %p\n",char_b);

    return 0;
}

測試結果4*不同機器顯示的記憶體地址會略有不同*
  &char_a : 0xbfebf947
 &short_a : 0xbfebf944
   &int_a : 0xbfebf940
   &int_b : 0xbfebf930
  &char_b : 0xbfebf948

**分析:案例3和4可以說明陣列型別會在規則1的前提下,滿足規則3.
對於char型別變數,陣列變數會存到高地址
對於int型別變數,陣列變數會存到低地址
跟陣列定義在前後沒有關係**

測試案例5#include <stdio.h>

int main(int argc, const char *argv[])
{
    double b[4];
    double a;
    printf("  &double_a : %p\n",&a);
    printf("  &double_b : %p\n",b);

    return 0;
}

測試結果:
*不同機器顯示的記憶體地址會略有不同*
 &double_a : 0xbfa3b688
 &double_b : 0xbfa3b668

測試案例6#include <stdio.h>

int main(int argc, const char *argv[])
{ 
double a;
    double b[4];
    printf("  &double_a : %p\n",&a);
    printf("  &double_b : %p\n",b);

    return 0;
}

測試結果:
*不同機器顯示的記憶體地址會略有不同*
 &double_a : 0xbfd3bda8
 &double_b : 0xbfd3bd88

**分析:由案例5和6可知、
對於double型別變數,陣列變數會存到低地址記憶體上,非陣列變數會先對存到較高記憶體上,而與它們定義的先後沒有關係

總結分析:由上面的結果(1和2的測試)也可以看到,在佔位不同的資料型別相鄰的記憶體會自動對齊佔位較高的記憶體。對齊方式是在高位佔有自己資料大小的空間.**

在陣列方面還有short、unsigned int等沒有測試,測試方法和案例5、6的方法一樣,感興趣的讀者自行驗證……

因本人時間和水平有限,文中如有錯訛、不當之處,敬請大神斧正。

相關推薦

C語言區域性變數記憶體順序

首先總結規則,詳細分析見下面: 規則1:記憶體由低到高優先分配給佔位8位元組、4位元組、2位元組、1位元組的資料型別 資料型別佔位說明: 8位元組:double、longlong int 4

c語言區域性變數記憶體地址分配順序

測試程式: #include <stdio.h> int main(){ unsigned int ui = 10; char c = 11; unsigne

c語言區域性變數應該注意什麼?

去年我們部門在17屆大學生在轉正述職答辯時,有位同學(同事)被領導提出一個問題:“c語言區域性變數應該注意什麼?” 當時我的第一反應就是,static靜態變數,命名與全域性變數避免衝突。我記得那位同學說的是注意記憶體,今天突然想到這個問題,我就把知道的都寫出來了(歡迎大家在下面進行修正和補充

C語言--區域性變數作為指標返回值的問題

程式碼: #include <stdio.h> #include <stdlib.h> int* getStu(int x, int y) {         int* i;         *i = x+y;         return i; }

C 程式區域性變數的理解

        寫這篇總結的緣由僅僅出於巧合,五一前幫一位同學看51的程式,在檢視彙編程式碼的時候(事實上我當時的彙編知識基本都還給了老師),無意中問起我“某個區域性變數的宣告怎麼沒有對應的彙編語句”,我沒有答出來。當時也只是把它當做一種常識給記了下來,平時不論還是在DSP

c語言區域性變數預設初始值

C語言中,定義區域性變數時如果未初始化,則值是隨機的,這是為什麼呢?定義區域性變數,其實就是在棧中通過移動棧指標來給程式提供一個記憶體空間和這個區域性變數名繫結。因為這段記憶體空間在棧上,而棧記憶體是反

(重要!)java資料的5種儲存位置(堆與) 成員變數區域性變數記憶體分配

來源: java中資料的5種儲存位置(堆與棧) http://blog.csdn.net/ghost_programmer/article/details/40891735 http://www.cnblogs.com/newveg/p/6591435.html

C語言有趣問題_區域性變數空間分配

有時候,在C語言的迴圈中,如果程式設計時對邊界判斷錯誤,就會帶來意想不到的結果,小白在本文中提及一個有趣的C語言問題,此問題並不是小白原創,而是一本程式設計書的考核內容,小白將其分享到此。 C語言有趣的問題## 先看程式碼: #include <st

C語言變數記憶體分配

轉載 轉自:http://blog.csdn.net/chenyiming_1990/article/details/9476181 今晚看了人家寫的一個關於C語言記憶體分配的帖子,發現真是自己想找的,於是乎就收藏了。。。 先看一下兩段程式碼: [cpp] vie

C語言資料在記憶體的儲存

一個由C/C++編譯的程式佔用的記憶體分為以下幾個部分:1、棧區(stack)— 由編譯器自動分配釋放 ,存放為執行函式而分配的區域性變數、函式引數、返回資料、返回地址等。 其操作方式類似於資料結構中

C語言全域性變數那些事兒(深入C最隱祕的地帶)

【雖然自認為對C的角角落落都有所瞭解,但直到看到這篇文章,才知道C中的一些隱祕的坑,是自己之前不知道的。 關於全域性變數的連結問題,之前在我部落格的某文章中有介紹過,一般對C有些瞭解的程式設計師都知道這個問題,但本文最後所提到的使用動態連結庫所出現的問題,著實讓我震驚。

C/C++語言在標頭檔案定義全域性變數

轉載:http://blog.csdn.net/chenqiai0/article/details/8490665 全域性變數可不可以定義在可被多個.C檔案包含的標頭檔案中?為什麼? 可以,在不同的C檔案中以static形式來宣告同名全域性變數。標頭檔案中不可以直接定

c語言全域性變數區域性變數問題彙總(轉)

1、區域性變數能否和全域性變數重名? 答:能,區域性會遮蔽全域性。要用全域性變數,需要使用"::" 區域性變數可以與全域性變數同名,在函式內引用這個變數時,會用到同名的區域性變數,而不會用到全域性變數。對於有些編譯器而言,在同一個函式內可以定義多個同名的區域性變數,比如在兩

C語言 全域性變數區域性變數的大小限制(關於堆疊的劃定)

下午做最長公共子序列的時候遇到的問題,問了felix後恍然大悟...看程式碼 #include <stdio.h> int main(){ int a[1000000];//區域性變數 return 0; } 編譯執行後發現溢位錯誤。 #include <

c語言如何操作記憶體(資料型別、函式在記憶體解析簡介)

1、用變數名來訪問記憶體 (c語言對記憶體地址的封裝:資料型別、函式名) ---【直接訪問記憶體(使用地址)】              資料型別:表示一個記憶體格子的長度和解析方法。(記憶體編址的單位是一個位元組)               (int *) 0; 

C語言-全域性變數區域性變數、全域性函式與內部函式

變數的宣告與定義: Int a;是定義型宣告,既是宣告又是定義,需要分配儲存空間Extern a;是引用型宣告,只是宣告,不需要分配儲存空間1、全域性變數與區域性變數 全域性變數: 編譯時分配記憶體,放在靜態儲存區裡,習慣:首字母大寫;。可以使用extern擴充套件全域性

C語言全域性變數區域性變數總結

————————————————————————————————————————————————————————————————————————————— 只有不斷的學習,不斷的進步,才能不被替代! 只有你的不可替代性才決定你的價值! -----2016年11月18

c語言全域性變數區域性變數

全域性變數: (1)在函式外定義 (2)在全域性可見 (3)一般在程式頂部定義 (4)存放在記憶體的全域性資料區 (5)如在定義時未初始化,則其值為0 (6)如果一個函式修改了全域性變數,則所有其他的函式都會看到修改後的變數 區域性變數: (1)

關於c語言全域性變數區域性變數

 #include<stdio.h> //register m; 1.錯誤,register不能定義為全域性變數; //static register m;2.靜態變數下不能定義為register變數; extern m;//3.全域性變數預設為static型別

【轉載】c語言全域性變數區域性變數問題彙總

1、關鍵字static的作用是什麼?定義靜態變數 2、static有什麼用途?網上答案: 1).限制變數的作用域(在程式的整個執行期間都不釋放) 2).設定變數的儲存域(儲存在靜態儲存區內) 譚浩強C語言page180: (1)對區域性變數用static宣告,則為該變數分