彻底理解字节序
2015-05-30 22:18
211 查看
假设我们有一个16位整数,那么它是由2个字节组成的。
首先,我们引出一个概念,数据高字节和数据低字节。
特别要强调的是,这里的指的是数据表示形式上的高字节和低字节,不涉及(不依赖)任何存储上的具体实现。
因为后面我就会引入另一个概念,内存低地址和内存高地址。
由于计算机内存地址的基本单位是字节,也就是说每个字节占一个地址值。
那么16位整数需要2个自己的存储空间,即需要占用2个内存地址。
还有两个术语是我们会经常见到的,那就是MSB(most significant bit)和LSB(least significant bit)。
MSB和LSB都是针对数据表示形式而言的,同样也不涉及(不依赖)任何存储上的具体实现。
MSB指的是最高有效位,是数字最左边的一位。LSB指的是最低有效位,是数字最右边一位。
在讨论字节序问题上,如果文章上来不先把概念特别强调清楚,我们很容易产生混淆。
下面,我们将引出这篇文章最重要的概念了,小端(little-endian)和大端(big-endian)。
小端指的是将数据小的一端(即数据低字节)存储在起始地址(即低地址)。
小端指的是将数据大的一端(即数据高字节)存储在起始地址(即低地址)。
我们把某个主机的CPU所用的字节序称为主机字节序。
TCP/IP规定采用大端字节序来传送网络协议数据包中的多字节整数数据。也就是说网络字节序等于大端字节序。
下面我们要讲解位序了。位序与字节序一般是保持一致的。
在C语言中,位域与结构体类似,其语法规定:先声明的成员位于低地址,后声明的成员位于高地址。
那么下面的位域中:
typedef struct OneByte
{
bt0 : 1;
bt1 : 1;
bt2 : 1;
bt3 : 1;
bt4 : 1;
bt5 : 1;
bt6 : 1;
bt7 : 1;
}
成员bt0就位于一个字节中最低地址bit0处,成员bt7就位于一个字节的最地址bit7处。
上面讲的是原理,下面讲一些具体实现。
宏定义__BYTE_ORDER定义在glibc的endian.h中,其值要么为__LITTLE_ENDIAN,要么为__BIG_ENDIAN
应用程序代码中可以用如下的语句来判断大小端,#if __BYTE_ORDER == __LITTLE_ENDIAN
但是,宏定义__BYTE_ORDER不一定存在于别的libc中,因此应用程序代码中在使用__BYTE_ORDER之前还需要实现判断libc的类型。
那么如何判断你的代码使用的libc是不是glibc呢?
使用这个宏定义进行判断#ifdef __GLIBC__ ,
The symbol __GLIBC__ is defined in the header features.h, and features.h is include by stdio.h
glibc-2.19-svnr25243/libc/ports/sysdeps/unix/sysv/linux/mips/bits/endian.h
里面通过判断__MIPSEB__还是__MIPSEL__来给__BYTE_ORDER定义不同的值。
#ifdef __MIPSEB__
# define __BYTE_ORDER __BIG_ENDIAN
#else
# ifdef __MIPSEL__
# define __BYTE_ORDER __LITTLE_ENDIAN
# endif
#endif
那么__MIPSEB__和__MIPSEL__来自何方呢?
还是在同样的头文件中,我看到如下注释,重点是我加粗的文字。
The MIPS architecture has selectable endianness.
Linux/MIPS exists in two both little and big endian flavours and we
want to be able to share the installed headerfiles between both,
so we define __BYTE_ORDER based on GCC's predefines.
这说明了__MIPSEB__和__MIPSEL__是定义在所用的交叉编译器里面的。
这里总结一下,glibc的大小端定义依赖于交叉编译器的预定义设置,而应用程序判断大小端又依赖于glibc的大小端定义。
首先,我们引出一个概念,数据高字节和数据低字节。
特别要强调的是,这里的指的是数据表示形式上的高字节和低字节,不涉及(不依赖)任何存储上的具体实现。
因为后面我就会引入另一个概念,内存低地址和内存高地址。
由于计算机内存地址的基本单位是字节,也就是说每个字节占一个地址值。
那么16位整数需要2个自己的存储空间,即需要占用2个内存地址。
还有两个术语是我们会经常见到的,那就是MSB(most significant bit)和LSB(least significant bit)。
MSB和LSB都是针对数据表示形式而言的,同样也不涉及(不依赖)任何存储上的具体实现。
MSB指的是最高有效位,是数字最左边的一位。LSB指的是最低有效位,是数字最右边一位。
在讨论字节序问题上,如果文章上来不先把概念特别强调清楚,我们很容易产生混淆。
下面,我们将引出这篇文章最重要的概念了,小端(little-endian)和大端(big-endian)。
小端指的是将数据小的一端(即数据低字节)存储在起始地址(即低地址)。
小端指的是将数据大的一端(即数据高字节)存储在起始地址(即低地址)。
我们把某个主机的CPU所用的字节序称为主机字节序。
TCP/IP规定采用大端字节序来传送网络协议数据包中的多字节整数数据。也就是说网络字节序等于大端字节序。
下面我们要讲解位序了。位序与字节序一般是保持一致的。
在C语言中,位域与结构体类似,其语法规定:先声明的成员位于低地址,后声明的成员位于高地址。
那么下面的位域中:
typedef struct OneByte
{
bt0 : 1;
bt1 : 1;
bt2 : 1;
bt3 : 1;
bt4 : 1;
bt5 : 1;
bt6 : 1;
bt7 : 1;
}
成员bt0就位于一个字节中最低地址bit0处,成员bt7就位于一个字节的最地址bit7处。
上面讲的是原理,下面讲一些具体实现。
宏定义__BYTE_ORDER定义在glibc的endian.h中,其值要么为__LITTLE_ENDIAN,要么为__BIG_ENDIAN
应用程序代码中可以用如下的语句来判断大小端,#if __BYTE_ORDER == __LITTLE_ENDIAN
但是,宏定义__BYTE_ORDER不一定存在于别的libc中,因此应用程序代码中在使用__BYTE_ORDER之前还需要实现判断libc的类型。
那么如何判断你的代码使用的libc是不是glibc呢?
使用这个宏定义进行判断#ifdef __GLIBC__ ,
The symbol __GLIBC__ is defined in the header features.h, and features.h is include by stdio.h
glibc-2.19-svnr25243/libc/ports/sysdeps/unix/sysv/linux/mips/bits/endian.h
里面通过判断__MIPSEB__还是__MIPSEL__来给__BYTE_ORDER定义不同的值。
#ifdef __MIPSEB__
# define __BYTE_ORDER __BIG_ENDIAN
#else
# ifdef __MIPSEL__
# define __BYTE_ORDER __LITTLE_ENDIAN
# endif
#endif
那么__MIPSEB__和__MIPSEL__来自何方呢?
还是在同样的头文件中,我看到如下注释,重点是我加粗的文字。
The MIPS architecture has selectable endianness.
Linux/MIPS exists in two both little and big endian flavours and we
want to be able to share the installed headerfiles between both,
so we define __BYTE_ORDER based on GCC's predefines.
这说明了__MIPSEB__和__MIPSEL__是定义在所用的交叉编译器里面的。
这里总结一下,glibc的大小端定义依赖于交叉编译器的预定义设置,而应用程序判断大小端又依赖于glibc的大小端定义。
相关文章推荐
- 数独游戏的求解过程
- 将Linux系统配置成基本路由器
- windows下多线程同步(利用事件对象,互斥对象,关键代码段)实现
- 使用 Velocity 模板引擎快速生成代码
- html响应式的方形多列布局
- Java调用调用了VB.netdll的C#dll的可行性
- Collections.sort(list)排序需要实现comparable借口
- AOP 那点事儿
- 希尔排序
- [HDU 1111]--Secret Code
- 2015第22周六Java反射、泛型、容器简介
- 三角函数计算,Cordic 算法入门
- 快速找出故障机器
- POJ1046 Color Me Less(水题就当玩吧)
- 构建者模式(Builder)示例代码
- 一摞烙饼的排序
- JSON入门学习案例笔记
- oracle存储过程中的select语句
- WordPress通过文章ID获取文章标题内容等信息。
- 浅析toString()和toLocaleString()的区别