大端模式和小端模式
对于整型和长整型等数据类型,big endian 认为第一个字节在高位字节(按照地址从低到高的顺序存放数据的高位字节和低位字节),而little endian则相反,认为第一个字节是最低位字节(按照从低地址到高地址的顺序存放数据的地位字节和高位字节)。
例如:假设从内存地址0x0000开始有以下数据:
0x0000 0x0001 0x0002 0x0003
0x12 0x34 0xab 0xcd
如果我们去读取一个地址为0x0000四字节的变量,若字节序为big-endian,则读出的结果为 0x1234abcd 若字节序为little-endian,则读出的结果为0xcdab3412
如果我们将0x1234abcd写入到以0x0000开始的内存中,则little-endian和big-endian模式的存放结果如下地址
地址: 0x0000 0x0001 0x0002 0x0003
big-endian 0x12 0x34 0xab 0xcd
little-endian 0xcd 0xab 0x34 0x12
一般来说,x86系列cpc都是低字节序的,powerpc通常是big-endian还有的cpu能通过跳线来调节cpu是工作于little-endian还是big-endian模式
对于0x12345678的存储:
小端模式(从低字节到高字节)低位地址0x78 0x56 0x34 0x12 高位地址
大端模式(从高字节到低字节)低位地址0x12 0x34 0x56 0x78 高位地址
main(){
char *sz; =“0123456789”;
int *p= (int *)sz;
printf("%x\n",*++p);
}
字符0对应的十六进制是0x30,请问程序输出是多少?
只要考察的目的是大端问题和小端问题
对于intel的cpu是小端模式,如果出现跨多个自己的数据类型,如int,long等,低地址存储数据的低位,高地址存储数据的高位
地址从@0开始,那么sz在内存的存储为
@0 @1 @2 @3 @4 @5 @6 @7 @8 @9
0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39
当你把char *强制转换成int * 后,因为int 占四个字节,那么p指向@0,并且*p占用的内存是@0@1@2@3打印的时候先执行++p操作,那么p指向@4,此时*p占有的地址
为@4@5@6@7,根据上面的低地址存低位,高地址存高位的解释,那么*p应该等于0x370x360x350x34
int a=0x12345678
char *p = (int *)&a;
printf("%x\n",*(p+1));
例如对于0x12345678,大部分unix机器和网络是这样0x12 0x34 0x56 0x78,这种方式成为big-endian
题目中的p指向0x78 加1 后指向0x56
二、大端小端转换方法
big-endian 转换为little-endian
#define bigtolittle16(A) ((((uint16(A) & 0xff00)>>8|(((uint16(A)&0x00ff)<<8))
#define bigtolittle32(a) ((((uint32(A)&0xff000000)>>24 |\
(((uint32(A)&0x00ff0000)>>8 |\
(((uint32(A)&0x0000ff00)<<8 |\
(((uint32(A)&0x000000ff)<<24 ))
#include "stdio.h"
int main(){
int i = 1;
char *p = ( char *)&i;
if( *p == 1){
printf("little endian\n");
}else{
printf("big endian\n");
}
}