关于大端模式和小端模式

关于大端模式和小端模式

大端模式是符合人的正常思维的,低地址存放高位,这样和我们从左往右看的方式是一样的(因为我们取地址总是取的是低地址);但是小端模式更符合计算机系统

网络协议中则是采用大端模式    http://www.cnblogs.com/fuchongjundream/p/3914770.html

在网络模式

在hackbucker的博客中讲的很详细,参考:http://blog.csdn.net/hackbuteer1/article/details/7722667

 一、总结博客中内容

从这篇文章中,我们可以知道这样一点,当我们对变量进行取地址的时候,其实我们取的是存放变量的低地址,所以我们可以采用查看取的地址存放的是变量的低位还是高位来判断是大端模式还是小端模式:

//取地址的方式检测大小端,因为取出的地址是低地址
void is_little_endian()
{
    printf("采用取地址的方式检测
");
    int a=0x0001;
    if(*(char*)&a==1)
        printf("It is Little-Endian
");
    else
        printf("It is Big-Endian
");
}


当然,我们也可以采用联合体的方式进行判断,因为如果是小端模式则存放方式为:

int a= 0x00001234;

char ch;

小端模式:

=======================

栈顶      高地址   0x00

                        0x00

                       0x12                      

栈底     低地址    0x34     ch;

==========================

大端模式

=======================

栈顶      高地址   0x34

                        0x12

                       0x00                     

栈底     低地址    0x00     ch;

==========================

void isLittleEndian()
{
    printf("采用联合体的方式检测
");
    union a
    {
        int k;
        char ch;

    }a;
    a.k=0x1;
    if(a.ch==0)
        printf("It is Big-Endian
");
    else
        printf("It is Little-Endian
");
}


当然我觉得最直观的方式就是定义一个整数int a=0x1;int*b=&a;然后debug模式下,Alt+6调出内存观察窗口,观察内存中a所在的地址存放的内容。

 二、自己的疑问和解答

1.栈

但是文中有一点没有理解,就是

----------------------- 最高内存地址 0xffffffff
栈底

栈顶
-----------------------

NULL (空洞)
-----------------------

-----------------------
未初始 化的数据
----------------------- 统称数据段
初始化的数据
-----------------------
正 文段(代码段)
----------------------- 最低内存地址 0x00000000
由图可以看出,再内存分布中,栈是向下增长的,而堆是向上增长的。

以上图为例如果我们在栈 上分配一个unsigned char buf[4],那么这个数组变量在栈上是如何布局的呢?看下图:
栈底 (高地址)
----------
buf[3]
buf[2]
buf[1]
buf[0]
----------
栈顶 (低地址)

从这里我并没有看出栈是向下增长的啊,因为栈顶是在高地址啊 ,每次push的时候都是向上增长的啊 ,为什么是向下增长的呢?于是在VS上进行了一番实验

声明一个数组,并定义

int a[10];
 int *b[10];
 for(int i=0;i<10;i++)
 {
  a[i]=i;
  b[i]=&(a[i]);
 }

则可以发现这个数组的存放方式是按照栈的方式存放的,从低地址向高地址存放的,依次向上增长,对于每个int类型是按照小端模式存放的;

如下图所示:

0x0035F830  01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00  ...................
0x0035F843  00 06 00 00 00 07 00 00 00 08 00 00 00 09 00 00 00 cc cc

所以我们应该知道为什么我们可以用指针自增或者自减的方式来访问数组了吧,它真的是代表地址的增减。

如果接下来声明:

int k=0xf;

则会发现b的地址比数组的地址都要低,则说明栈中的数据是按照地址向下增长的方式存放的。

2.堆的增长方式

int *m=new int(0xf);
 int *n=new int[10];
 for(int i=0;i<10;i++)
  n[i]=i;

 

下面观察堆中的地址是怎么增长的,同样采用debug模式下,Alt+6调出内存观察器窗口

n中存放的地址为0x00204508,可以看出该数组存放的方式和栈中数组是相同的,

0x00204508  00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00  ...................
0x0020451B  00 05 00 00 00 06 00 00 00 07 00 00 00 08 00 00 00 09 00  ...................
0x0020452E  00 00

不同的是m的地址,m中存放的地址为0x002044c8,则我们可以发现,m的地址比n的地址要低,所以可以看出,堆整个的增长方式是向上增长的。

原文地址:https://www.cnblogs.com/limera/p/5468173.html