大小端

大小端

CPU架构:

  1. PowerPC系列采用大端(big endian)的方式存储数据,
  2. X86系列则采用小端(little endian)方式存储数据。
  3. ARM芯片默认采用小端,但可以切换为大端;

编译器:

  1. 在C语言中,默认是小端(但在一些对于单片机的实现中却是基于大端,比如Keil 51C)
  2. Java是平台无关的,默认是大端
  3. 在网络上传输数据普遍采用的都是大端。

在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为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占一个地址。
在这里插入图片描述

  1. unsigned char 表示

在这里插入图片描述

  1. unsigned short 表示

在这里插入图片描述

  1. unsigned int 表示
    在这里插入图片描述

  2. 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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值