码迷,mamicode.com
首页 > 其他好文 > 详细

栈增长方向与大端/小端问题

时间:2016-05-02 18:32:56      阅读:240      评论:0      收藏:0      [点我收藏+]

标签:

转:http://www.cnblogs.com/xkfz007/archive/2012/06/22/2558935.html

栈增长和大端/小端问题是和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地址相比较
如果值为正,则堆栈向高地址增长;否则,堆栈向低地址增长

 转:http://blog.csdn.net/woxiaozhi/article/details/6891356

大端/小端就是Big-Endian/Little-Endian问题

大端格式:

在这种格式中,字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中。

小端格式:

与大端存储格式相反,在小端存储格式中,低地址中存放的是字数据的低字节,高地址存放的是字数据的高字节。

请写一个C函数,若处理器是Big_endian的,则返回0;若是Little_endian的,则返回1

解答:

int checkCPU( )

{

    {

           union w

           {  

                  int  a;

                  char b;

           } c;

           c.a = 1;

           return(c.b ==1);

    }

}

 

剖析:

嵌入式系统开发者应该对Little-endian和Big-endian模式非常了解。例如,16bit宽的数0x1234在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:

内存地址

0x4000

0x4001

存放内容

0x34

0x12

而在Big-endian模式CPU内存中的存放方式则为:

内存地址

0x4000

0x4001

存放内容

0x12

0x34

 

32bit宽的数0x12345678在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:

内存地址

0x4000

0x4001

0x4002

0x4003

存放内容

0x78

0x56

0x34

0x12

而在Big-endian模式CPU内存中的存放方式则为:

内存地址

0x4000

0x4001

0x4002

0x4003

存放内容

0x12

0x34

0x56

0x78

联合体union的存放顺序是所有成员都从低地址开始存放。

 

下面附上 另一段代码吧,摘自一个开源项目

int  big_endian (void)

     {
       union{
          long l;
          char c[sizeof(long)];
       }u;
 
       u.l = 1;
       return  (u.c[sizeof(long) - 1] == 1);
     }
  

   有时候,用C语言写程序时需要知道是大端模式还是小端模式。 所谓的大端模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;所谓的小端模式,是指数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中。为什么会有大小端模式之分呢?这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如果将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。例如一个16bit的short型x,在内存中的地址为0x0010,x的值为0x1122,那么0x11为高字节,0x22为低字节。对于大端模式,就将0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。小端模式,刚好相反。我们常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。

下面这段代码可以用来测试一下你的编译器是大端模式还是小端模式:
 
short int x;

char x0,x1;

x=0x1122;

x0=((char*)&x)[0];  //低地址单元
x1=((char*)&x)[1];  //高地址单元

若x0=0x11,则是大端; 若x0=0x22,则是小端

栈增长方向与大端/小端问题

标签:

原文地址:http://www.cnblogs.com/shirishiqi/p/5452662.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!