[过去写的,贴过来重温一下,顺便奉送一个判断机器大小尾的代码]
今天在网上看到这样一道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;
}
文章评论(0条评论)
登录后参与讨论