大小端
CPU架构:
- PowerPC系列采用大端(big endian)的方式存储数据,
- X86系列则采用小端(little endian)方式存储数据。
- ARM芯片默认采用小端,但可以切换为大端;
编译器:
- 在C语言中,默认是小端(但在一些对于单片机的实现中却是基于大端,比如Keil 51C)
- Java是平台无关的,默认是大端
- 在网络上传输数据普遍采用的都是大端。
在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器)。另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如果将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。
大端模式(big endian) :数据高位存储在内存低地址,低位对应高地址 ;
小端模式(little endian):数据高位存储在内存高地址,低位对应低地址 ;
int 型变量 a=0x12345678 占用 4 个字节,
在大端字节序的机器上,int 数据的高位位于低地址。
在小端字节序的机器上,int 数据的高位位于高地址。
VS2015 查看x86架构为小端表示
想要查看内存,局部变量等窗口的话,首先要确保在调试状态下(按F5或者按本地windows 调试器)进行,然后点击调试-》窗口-》内存即可;然后弹出一个窗口1,
将变量,一个unsigned char占一个地址。
- unsigned char 表示
- unsigned short 表示
-
unsigned int 表示
-
unsigned long long 表示
内存相同表示
想要在CPU中按 字节为最小单位表示数组,则定义
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
unsigned char a8[8] = { 0x01,0x23 ,0x45 ,0x67 ,0x89,0xab,0xcd,0xef };
unsigned short a16[4] = { 0x2301,0x6745 ,0xab89,0xefcd };
unsigned int a32[2] = { 0x67452301 ,0xefcdab89 };
unsigned long long a64[2] = { 0xefcdab8967452301 ,0x1};
内存均为
相互转换
#include <stdio.h>
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef int i32;
#define LITTLE_ENDIAN
//#define BIG_ENDIAN
#define ROTR32(x,n) (((x)>>(n))|((x)<<(32-(n))))
#ifdef BIG_ENDIAN
#define EXT_BYTE32(x,n) ((u8)((u32)(x)>>(8*(n))))
#define INS_BYTE32(x,n) ((u32)(x)<<(8*(n)))
#define U32BIG(x) (x)
#endif
#ifdef LITTLE_ENDIAN
#define EXT_BYTE32(x,n) ((u8)((u32)(x)>>(8*(3-(n)))))
#define INS_BYTE32(x,n) ((u32)(x)<<(8*(3-(n))))
#define U32BIG(x) \
((ROTR32(x, 8) & (0xFF00FF00)) | \
((ROTR32(x, 24) & (0x00FF00FF))))
#endif
//big endian
void load64BIG(u64* x, u8* S) {
int i;
*x = 0;
for (i = 0; i < 8; ++i)
*x |= ((u64)S[i]) << (7 - i) * 8;
}
void store64BIG(u8* S, u64 x) {
int i;
for (i = 0; i < 8; ++i)
S[i] = (u8)(x >> (7 - i) * 8);
}
//little endian
void load64LIT(u64* x, u8* S) {
int i;
*x = 0;
for (i = 0; i < 8; ++i)
*x |= ((u64)S[i]) << i * 8;
}
void store64LIT(u8* S, u64 x) {
int i;
for (i = 0; i < 8; ++i)
S[i] = (u8)(x >> i * 8);
}
#define NUM 16
int main()
{
u8 in[NUM], in1[NUM] = { 0 }, i;
for (i = 0; i < NUM; i++) {
in[i] = i;
}
printf("u8 :");
for (i = 0; i < NUM; i++) {
printf("%02x,", in[i]);
}
printf("\n");
//U32 大小端
u32 a[4];
printf("\nu32:(big endian) :");
for (i = 0; i < NUM / 4; i++) {
a[i] = U32BIG(((u32*)(in))[i]);
printf("%08x,", a[i]);
}
printf("\nu32:(little endian):");
for (i = 0; i < NUM / 4; i++) {
a[i] = ((u32*)(in))[i];
printf("%08x,", a[i]);
}
printf("\n");
//U64 大小端
u64 a1[4];
printf("\nu64:(big endian) :");
load64BIG(&a1[0], in);
printf("%016llx,", a1[0]);
store64BIG(in1, a1[0]);
printf("\nu64:(little endian):");
load64LIT(&a1[0], in);
printf("%016llx\n", a1[0]);
store64LIT(in1, a1[0]);
printf("\n");
return 0;
}