大端小端模式判断以及数据转换
生活随笔
收集整理的這篇文章主要介紹了
大端小端模式判断以及数据转换
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
簡介
在計算機系統中,我們是以字節為單位的,每個地址單元都對應著一個字節,一個字節為 8bit。但是在C語言中除了8bit的char之外,還有16bit的short型,32bit的long型(要看具體的編譯器),另外,對于位數大于 8位的處理器,例如16位或者32位的處理器,由于寄存器寬度大于一個字節,那么必然存在著一個如何將多個字節安排的問題。因此就導致了大端存儲模式和小端存儲模式。考慮一個short整數0xAF32(0x32是低位,0xAF是高位),把它賦值給一個short變量,那么它在內存中的存儲可能有如下兩種情況:
- 大端字節(Big-endian):較高的有效字節存放在較低的存儲器地址,較低的有效字節存放在較高的存儲器地址。
- 小端字節(Big-endian):字數據的高字節存儲在高地址中,而字數據的低字節則存放在低地址中。地址 0x2000 0x2001+-+-+-+-+-+-+-+-+ 大端存儲 | 0xAF | 0x32 |+-+-+-+-+-+-+-+-+ 小端存儲 | 0x32 | 0xAF |+-+-+-+-+-+-+-+-+
C函數判斷大小端
判斷計算機的存儲方式:
// 是小端模式則返回1,否則返回0 int is_little_endian() {union w{int x ;char y ;}c ;c.x = 1;return (c.y==1); }大端模式和小端模式轉換
#include<stdio.h>typedef unsigned int uint_32 ; typedef unsigned short uint_16 ;#define BSWAP_16(x) \(uint_16)((((uint_16)(x) & 0x00ff) << 8) | \(((uint_16)(x) & 0xff00) >> 8) \) #define BSWAP_32(x) \(uint_32)((((uint_32)(x) & 0xff000000) >> 24) | \(((uint_32)(x) & 0x00ff0000) >> 8) | \(((uint_32)(x) & 0x0000ff00) << 8) | \(((uint_32)(x) & 0x000000ff) << 24) \)uint_16 bswap_16(uint_16 x) {return (((uint_16)(x) & 0x00ff) << 8) | \(((uint_16)(x) & 0xff00) >> 8) ; } uint_32 bswap_32(uint_32 x) {return (((uint_32)(x) & 0xff000000) >> 24) | \(((uint_32)(x) & 0x00ff0000) >> 8) | \(((uint_32)(x) & 0x0000ff00) << 8) | \(((uint_32)(x) & 0x000000ff) << 24) ; } int main(int argc,char *argv[]) {printf("------------帶參宏-------------\n");printf("%#x\n",BSWAP_32(0x12345678));printf("%#x\n",BSWAP_16(0x1234)) ;printf("------------函數調用-----------\n");printf("%#x\n",bswap_32(0x12345678));printf("%#x\n",bswap_16(0x1234)) ;return 0 ; }兩種模式的使用現狀
Intel的80x86系列芯片是唯一還在堅持使用小端的芯片,ARM芯片默認采用小端,但可以切換為大端;而MIPS等芯片要么采用全部大端的方式儲存,要么提供選項支持大端——可以在大小端之間切換。另外,對于大小端的處理也和編譯器的實現有關,在C語言中,默認是小端(但在一些對于單片機的實現中卻是基于大端,比如Keil 51C),Java是平臺無關的,默認是大端。在網絡上傳輸數據普遍采用的都是大端。
#include <stdio.h> struct ST{short val1;short val2; }; union U{int val;struct ST st; };int main(void) {int a = 0;union U u1, u2;a = 0x12345678;u1.val = a;printf("u1.val is 0x%x\n", u1.val);printf("val1 is 0x%x\n", u1.st.val1);printf("val2 is 0x%x\n", u1.st.val2);printf("after first convert is: 0x%x\n", htonl(u1.val));u2.st.val2 = htons(u1.st.val1);u2.st.val1 = htons(u1.st.val2);printf("after second convert is: 0x%x\n", u2.val);return 0; }shell命令判斷大小端模式
- dpkg-architecture命令$ dpkg-architecture DEB_BUILD_ARCH=arm64 DEB_BUILD_ARCH_ABI=base DEB_BUILD_ARCH_BITS=64 DEB_BUILD_ARCH_CPU=arm64 DEB_BUILD_ARCH_ENDIAN=little DEB_BUILD_ARCH_LIBC=gnu DEB_BUILD_ARCH_OS=linux DEB_BUILD_GNU_CPU=aarch64 DEB_BUILD_GNU_SYSTEM=linux-gnu DEB_BUILD_GNU_TYPE=aarch64-linux-gnu DEB_BUILD_MULTIARCH=aarch64-linux-gnu DEB_HOST_ARCH=arm64 DEB_HOST_ARCH_ABI=base DEB_HOST_ARCH_BITS=64 DEB_HOST_ARCH_CPU=arm64 DEB_HOST_ARCH_ENDIAN=little DEB_HOST_ARCH_LIBC=gnu DEB_HOST_ARCH_OS=linux DEB_HOST_GNU_CPU=aarch64 DEB_HOST_GNU_SYSTEM=linux-gnu DEB_HOST_GNU_TYPE=aarch64-linux-gnu DEB_HOST_MULTIARCH=aarch64-linux-gnu DEB_TARGET_ARCH=arm64 DEB_TARGET_ARCH_ABI=base DEB_TARGET_ARCH_BITS=64 DEB_TARGET_ARCH_CPU=arm64 DEB_TARGET_ARCH_ENDIAN=little DEB_TARGET_ARCH_LIBC=gnu DEB_TARGET_ARCH_OS=linux DEB_TARGET_GNU_CPU=aarch64 DEB_TARGET_GNU_SYSTEM=linux-gnu DEB_TARGET_GNU_TYPE=aarch64-linux-gnu DEB_TARGET_MULTIARCH=aarch64-linux-gnu
- lscpu命令$ lscpu Architecture: aarch64 Byte Order: Little Endian CPU(s): 4 On-line CPU(s) list: 0-3 Thread(s) per core: 1 Core(s) per socket: 4 Socket(s): 1 Vendor ID: ARM Model: 4 Model name: Cortex-A53 Stepping: r0p4 CPU max MHz: 1296.0000 CPU min MHz: 408.0000 BogoMIPS: 48.00 L1d cache: unknown size L1i cache: unknown size L2 cache: unknown size Flags: fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
延伸閱讀:
準確詳解:C/C++ float、double數據類型的表示范圍及精度
?
總結
以上是生活随笔為你收集整理的大端小端模式判断以及数据转换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ns2相关学习——TCL脚本编写(2)
- 下一篇: yum安装rz、