堆、棧增長方向和大端、小端問題

棧增長方向與大端/小端問題

棧增長和大端/小端問題是和CPU相關的兩個問題。
在內存管理中,與棧對應是堆。對於堆來講,生長方向是向上的,也就是向着內存地址增加的方向;對於棧來講,它的生長方式是向下的,是向着內存地址減小的方向增長。在內存中,“堆”和“棧”共用全部的自由空間,只不過各自的起始地址和增長方向不同,它們之間並沒有一個固定的界限,如果在運行時,“堆”和 “棧”增長到發生了相互覆蓋時,稱爲“棧堆衝突”,系統肯定垮臺。
在常見的x86中內存中棧的增長方向就是從高地址向低地址增長。
我們可以通過一些代碼來判斷棧的增長方向:
複製代碼
#include<stdio.h>  
static int stack_dir;  
static void find_stack_direction (void)  {  
    static char   *addr = NULL;   /* address of first
                                     `dummy', once known 
*/  
    char     dummy;          /* to get stack address */  

    if (addr == NULL)  
    {                           /* initial entry */  
        addr = &dummy;  

        find_stack_direction ();  /* recurse once */  
    }  
    else                          /* second entry */  
        if (&dummy > addr)  
            stack_dir = 1;            /* stack grew upward */  
        else  
            stack_dir = -1;           /* stack grew downward */  
}  

int main(void)  
{  
    find_stack_direction();  
    if(stack_dir==1)  
        puts("stack grew upward");  
    else  
        puts("stack grew downward");  
    return 0;  
複製代碼
                                                              
find_stack_direction函數使用函數遞歸的方法
第一次進入,由於addr爲NULL,所以將字符變量dummy的地址賦值給靜態變量addr
第二次進入,由於靜態變量addr已賦了值,所以進入 "Second entry."
接着,將第二次進入的dummy地址和第一次進入的dummy地址相比較
如果值爲正,則堆棧向高地址增長;否則,堆棧向低地址增長

大端/小端就是Big-Endian/Little-Endian問題
大端:高位字節存在低地址上,低位字節存在高地址上
小端:低位字節存在低地址上,高位字節存在高地址上 
有兩種常見的方法來判斷是大端還是小端
方法一:使用指針
int x=1;
if(*(char*)&x==1)
    printf("little-endian\n");
else
    printf("big-endian\n");
方法二:使用聯合
union{
    int i;
    char c;
}x;
x.i=1;
if(x.c==1)
    printf("little-endian\n");
else
    printf("big-endian\n");
下面是一個圖示:
下面的代碼是實現大端和小端整數的轉換:
int chgendian(int x){
    int x2=0;
    char *p=(char*)&x;
    int i=sizeof(int)-1;
    while(i>=0){
        x2|=*p<<(i*8);
        i--;
        p++;
    }
    return x2;
}

在stm32中,用的是小端存儲,即低字節在低位,高字節在高位。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章