大小端模式存储

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ziyuzhao123/article/details/24966911

一、存储模式

在存储方式上分为大端模式和小端模式:

大端模式(big_endian):字数据的高字节存储在低地址中,而字数据的低字节存放在高地址中。

小端模式(little_endian):字数据的高字节存储在高地址中,而字数据的低字节存放在低地址中。

C/C++语言编写的程序里数据存储顺序是跟编译平台所在的CPU相关的,PowerPC系列采用big endian方式存储数据,而x86系列则采用little endian方式存储数据。

而JAVA编写的程序则唯一采用big endian方式来存储数据。所有网络协议也都是采用big endian的方式来传输数据的。

二、确定当前系统的存储模式

编写C程序,确定当前系统的存储模式。

#include <iostream>
using namespace std;

int Is_little_Endian()
{
	union
	{
		int i;
		char ch;
	}c;
	c.i=1;
	return (c.ch == 1);
}

int main()
{
	cout<<Is_little_Endian()<<endl;
	return 0;
}
解析:union是所有的数据成员公用一个存储空间,变量i占4个字节,其中一个字节的值为1,其余三个字节的值为0,。如果取出低地址上的值为0,则是大端模式,如果取出低地址上的值为1,则是小端模式。

上面的程序在X86系统下,输出为1,是小端模式。

三、实例

在X86系统下,以下程序的输出为多少?

#include <stdio.h>
int main()
{
	int a[5]={1,2,3,4,5};
	int *ptr1=(int *)(&a+1);
	int *ptr2=(int *)((int)a+1);
	printf("%x\n%x\n",ptr1[-1],*ptr2);
	return 0;
}

程序输出:5    20000000

解析:
先来看ptr1,a是一个数组名,也就是数组的首地址。
a是一个数组名,也就是数组的首地址。对a进行取地址运算符,得到的是一个指向数组的指针!
也就相当于int (*ptr1) [5] = &a;ptr1是一个指针,它指向的是一个包含5个int元素的数组!那么执行ptr1+1后,ptr1的偏移量相当于 ptr1+ sizeof(int) * 5 !而程序中强制将指针ptr1转换成一个int* 那么 ptr1[ -1] 其实就是 ptr1 - sizeof(int)所以,ptr1[ -1] 指向了数组中得最后一个元素,也就是 5
&a是指向a[5]数组的头,&a+1指向哪里呢?如果我们把a[5]定义成a[2][5]我们就可以确定&a+1应该是指向a[1][0],是a[0][4]后面的一个单元,根据程序的运行结果,可以确定&a+1应该就是把a[5]像a[2][5]一样处理的,即&a+1指向了a[4]后面的一个单元,所以ptr1[-1]=*(ptr1-1)=5。

再看ptr2,(int)a先把a转化成int型,然后(int)a+1就是像int型一样处理了,这里的+1当然是向前增加一个字节,如果从0地址开始存储a[5]数组,所以(int)a+1应该指向如下图示:


(int*)又告诉编译器(int)a+1要按照int型指针处理,所以*ptr2指向的内存块的内容应该是:02 00 00 00


来自:《C语言深度剖析》



猜你喜欢

转载自blog.csdn.net/ziyuzhao123/article/details/24966911