(笔记)字节对齐与字节顺序及其处理

字节对齐

问题引入:

在写网络间进程通讯时,定义一个结构体用于发送,发现两个问题:

  1. 每个结构体前都加入#pragma pack (push,1),结尾加#pragma pack(pop) ,去掉后,sizeof()该结构体总字节数会变化。
  2. 结构体内成员的类型为uint8_t,uint16_t等。
    例子:
typedef struct{
	uint16_t one;
	uint32_t two;
	uint8_t three;
}Test

sizeof(Test)应该是16+32+8=56.,但他实际却为64。
这就是因为字节对齐。

原因及其处理

CPU在内存中寻址的最小单位是byte(字节),而1个byte等于8个bit(比特),为了提高CPU在内存中的存取数据的效率,CPU会按块操作,块的大小可能是1,2,4,8等等字节,这个大小就是字节对齐的边界,会直接影响到数据在内存的存储方式。
而块的大小由编译器和操作系统决定,通常32位系统默认4字节,在64位系统,默认8字节。所以,编译器会按默认的字节对齐为单位分配存储空间,如果不足,会自动补充空白的字节,因此导致结构体大小不一致。

因此,上述例子中,编译器选择的是uint16_t为单位,而不是uint8_t。从而使得16+32+16=64。

解决方法:不让编译器去设置字节对齐单位,而是手动设置字节对齐单位。通过:

#pragma  pack (push,1)  //把原来对齐方式设置压栈,并设新的对齐方式设置为一个字节对齐(能保留之前的对齐方式,这个更好)
...
#pragma pack(pop)   //恢复对齐状态
或
#pragma pack (n)     //让编译器按照n个字节对齐。
...
#pragma pack ()       //取消自定义字节对齐方式。

手动将对齐单位设为1字节。

字节顺序

问题引入:

利用socket网络进程间传输数据时,发送0xA5AA,结果接收端接收的是0xAA 0xA5,顺序出了问题。

原因及其处理

数据是以字节为单位存放的,所以就存在将数据按怎样的顺序存放的问题。两种方式。大端和小端。
以0xA5AA为例子,数据的高位是A5,低位是AA。

  • 大端序:指数据的低位保存在高地址,数据的高位保存在低地址。
    地址从低到高,则0xA5AA存放为0xA5 0xAA。
  • 小端序:数据的低位保存在低地址,数据的高位保存在高地址。
    地址从低到高,则0xA5AA存放为0xAA 0xA5。

TCP/IP协议中规定了网络字节序为大端序(规定接收到得第一个字节是高字节,存放到低地址,所以发送时会首先去低地址取数据的高字节。)
因此发送数据时,需要将主机字节序转换为网络字节序,而在接收端同样需要将网络字节序转换为主机字节序。
NBO : 网络字节序
HBO : 主机字节序

转换函数

linux的头文件 : #include <arpa/inet.h>

htons() : 由主机字节序转换为网络字节序的16位整数值。(host to net short)
ntohs() : 由网络字节序转换为主机字节序的16位整数值。
htonl () : 由主机字节序转换为网络字节序的32位整数值。(host to net long)
ntohl () : 由网络字节序转换为主机字节序的32位整数值。  

#include <endian.h>

htobe64(uint64_t host_64bits) :64字节主机转网络(大端)
htole64(uint64_t host_64bits);64字节主机转小端
be64toh(uint64_t big_endian_64bits) :64字节网络转主机
le64toh(uint64_t little_endian_64bits) ;64字节小端转主机
数字可为64,32,16,8

在实际中:
多字节数据包IP地址端口等需要进行处理。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值