原创 LittleEndian和BigEndian的区别以及数组名取地址

2008-8-1 16:26 2617 3 3 分类: 软件与OS

[过去写的,贴过来重温一下,顺便奉送一个判断机器大小尾的代码]


 


今天在网上看到这样一道c++的笔试题目:


int szNum[5] = { 1, 2, 3, 4, 5 };


int *ptrA = (int*)(&szNum + 1);


int *ptrB = (int*)( (int)szNum + 1);


std::cout << ptrA[-1] << *ptrB << std::endl;


 


其结果让我学到不少东西,现在就跟大家分享一下我的学习过程吧。


 


这道题目首先定义了一个有5个int型元素的数组;然后定义了两个指向int型的指针。最后输出一些结果。


 


第一个问题:&szNum是什么?它和szNum有区别嘛?


答案:有区别,szNum是数组名,它实际上可以看成是一个int*,指向数组首地


           址;而&szNum其值跟szNum一样,但是实际上它是一个int(*)[],即指向整


          个数组的指针,也就是说虽然szNum和&szNum的值是一样的,都指向数组


          首地址,但是它们的指针类型是不一样的,所以它们的加运算也就不一样


          了,szNum+1指向数组的第二个元素,而&szNum+1则跨过5个int型,指向


           szNum+5的位置。


                   知道了这一点,那么ptrA指向的其实就是5后面的内存区域了,至于


          ptrA[-1]? 我没见过这种形式哦。。。不过可以想到它应该就是5啦~~~hh。


 


        接下来再分析第二个输出,主要是考查你对LittleEndian和BigEndian的理解。


首先看(int)szNum,就是把int*强制转换为int,然后在这个基础上加1,在内存


里就是数组元素1的地址字节加了个1。还是不明白的话看下面的图:(地址是我


假设的)


 


0X0001 : 01    //元素1的地址为0x0001, 即szNum = 0x0001


0X0002 : 00   //这里就是(int)szNum+1 了,即(int)szNum+1 = 0x0002,注意


szNum+1 =? 想想


0X0003 : 00


0X0004 : 00


0X0005 : 02 //呵呵,szNum+1 = 0x0005,这里是元素2 的位置;int型是4个字节哦~~~


0X0006 : 00


0X0007 : 00


0X0008 : 00


        现在知道ptrB=0x0002了,那么*ptrB等于多少呢?恩,它是一个int型,即占4


个字节,等于0x00000002?


        错啦~~~应该等于0x02000000,为什么呢?这就跟LittleEndian和BigEndian有关


了。先来说说LittleEndian吧,因为我们使用的大部分机器都是LittleEndian的,对于


一个word(字,两个字节16位)数据来说,内存的高地址存放数据的高字节,低


地址存放数据的低字节,举个例子:0x1234,在内存中的存放方式如下:


 


0x0001:34 //低地址放哪个字节呢?恩,是低字节的数据34,哈哈


0x0002:12


 


BigEndian则正好相反了,高地址放低字节的,低地址放高字节的,这个不太符合


人们的思维习惯哦。:)


 


弄明白上面的,那么就知道*ptrB为什么等于0x02000000了吧


敲进你的编译器试试吧


结果是


5


33554432 //0x02000000的十进制就是33554432哦:)


 


#include <stdio.h>
//判断程序运行的平台是little-endian还是big-endian
bool IsLittleEndian()
{
 int i = 1;
 char* p = (char*)&i;
 return *p;
}
int main()
{
 if(IsLittleEndian())
  printf("LittleEndian\n");
 else
  printf("BigEndian\n");
 return 0;
}

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
3
关闭 站长推荐上一条 /3 下一条