一、[C/C++]大小端字节序转换程序 转自:https://www.cnblogs.com/wuyepeng/p/9833273.html
计算机数据存储有两种字节优先顺序:高位字节优先(称为大端模式)和低位字节优先(称为小端模式)。
大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;这和我们的阅读习惯一致。
小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低。
例子:对于内存中存放的数0x12345678来说
如果是采用大端模式存放的,则其真实的数是:0x12345678
如果是采用小端模式存放的,则其真实的数是:0x78563412
如果称某个系统所采用的字节序为主机字节序,则它可能是小端模式的,也可能是大端模式的。
而端口号和IP地址都是以网络字节序存储的,不是主机字节序,网络字节序都是大端模式。
要把主机字节序和网络字节序相互对应起来,需要对这两个字节存储优先顺序进行相互转化。
这里用到四个函数:htons(),ntohs(),htonl()和ntohl().
这四个地址分别实现网络字节序和主机字节序的转化,这里的h代表host,n代表network,s代表short,l代表long。
通常16位的IP端口号用s代表,而IP地址用l来代表。
1 2 3 4 5 6 |
|
htonl 表示 host to network long ,用于将主机 unsigned int 型数据转换成网络字节顺序;
htons 表示 host to network short ,用于将主机 unsigned short 型数据转换成网络字节顺序;
ntohl、ntohs 的功能分别与 htonl、htons 相反。
如图,i为int类型占4个字节,但只有1个字节的值为1,另外3个字节值为0;取出低地址上的值,当其为1时则为小端模式,为0时为大端模式。
//大小端模式的判断 //方法一:利用联合体所有成员的起始位置一致, //对联合体中的int类型赋值,然后判断联合体中char类型的值的大小
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
|
运行结果如下:
二、C/C++语言,对MSB、LSB的读/取处理 转自:https://blog.csdn.net/dijkstar/article/details/48765843
1. 做硬件的都知道,串口是LSB优先,I2C、1553B是MSB优先,这里的MSB、LSB指的是二进制位的位置,区别于【字节序】(通信中,先发送低字节,还是高字节的问题,那叫大端big-endian、小端little-endian)
如果需要自己来实现MSB、LSB的读取、转换,如何实现呢?下面给出C/C++程序:
#include "stdio.h"
#define BITS_WIDTH (8)
void main()
{
int val = 0;
int i=0;
//
//接收:MSB在最左边,先进来
//
for (i=0; i<BITS_WIDTH; i++)
{
val<<=1;
if(i==0 || i==7)//模拟第N位上有高位
val++;
}
printf("接收MSB在最左边1,0x%x\n", val);
//
//接收:MSB在最左边,先进来
//
val = 0;
for (i=0; i<BITS_WIDTH; i++)
{
if(i==0 || i==2)//模拟第N位上有高位
{
val |=1<<(BITS_WIDTH-1-i);
}
}
printf("接收MSB在最左边2,0x%x\n", val);
//
//接收:LSB在最左边,先进来
//
val = 0;
for (i=0; i<BITS_WIDTH; i++)
{
//模拟第N位上有高位
if(i==0 || i==1)
{
val |=1<<i;
}
}
printf("接收LSB在最左边,0x%x\n", val);
printf("\n");
//
//发送: 先发送高位,后发送低位
//
val= 0x25;
printf("发送数值0x%x按先高位后低位顺序: ", val);
for (i=0; i<BITS_WIDTH; i++)
{
if ((val&0x80) == 0)
printf("0, ");
else
printf("1, ");
val <<=1;
}
printf("\n");
//
//发送: 先发送低位,后发送高位
//
val= 0x25;
printf("发送数值0x%x按先低位后高位顺序: ", val);
for (i=0; i<BITS_WIDTH; i++)
{
if ((val&0x01) == 0)
printf("0, ");
else
printf("1, ");
val >>=1;
}
printf("\n");
}
2. 字节序的大端、小端:
x86系统用的是小端(little-endian),简单说:就是“先存储低字节,后存储高字节”,或者说“先低后高”
例如:unsigned int xyz = 0x0A0B0C0D;
内存中,先存储的0x0D, 0x0C, 0x0B,......,就是上面说的“先低后高”