大小端转换函数

套接字-Socket
来源: 爱编程的大丙

#include <arpa/inet.h>
// u:unsigned
// 16: 16位, 32:32位
// h: host, 主机字节序
// n: net, 网络字节序
// s: short
// l: int

// 这套api主要用于 网络通信过程中 IP 和 端口 的 转换
// 将一个短整形从主机字节序 -> 网络字节序
uint16_t htons(uint16_t hostshort);	
// 将一个整形从主机字节序 -> 网络字节序
uint32_t htonl(uint32_t hostlong);	

// 将一个短整形从网络字节序 -> 主机字节序
uint16_t ntohs(uint16_t netshort)
// 将一个整形从网络字节序 -> 主机字节序
uint32_t ntohl(uint32_t netlong); 

IP地址转换

//主机字节序的IP地址转换为网络字节序
//主机字节序的IP是一个字符串,网络字节序IP是一个整形
int inet_pton(int af, const char *src, void *dst);

1. af: 地址族(IP地址的家族包括ipv4和ipv6)协议

AF_INET: ipv4格式的ip地址

AF_INET6: ipv6格式的ip地址

2. src: 传入参数, 对应要转换的点分十进制的ip地址: 192.168.1.100

3. dst: 传出参数, 函数调用完成, 转换得到的大端整形IP被写入到这块内存中

返回值:成功返回1,失败返回0(参数2有无效字符)或者-1(参数1无效地址)

#include <arpa/inet.h>
// 将大端的整形数, 转换为小端的点分十进制的IP地址        
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);

1. af: 地址族协议

AF_INET: ipv4格式的ip地址

AF_INET6: ipv6格式的ip地址

2. src: 传入参数, 这个指针指向的内存中存储了大端的整形IP地址

3. dst: 传出参数, 存储转换得到的小端的点分十进制的IP地址

4. size: 修饰dst参数的, 标记dst指向的内存中最多可以存储多少个字节

返回值: 成功: 指针指向第三个参数对应的内存地址, 通过返回值也可以直接取出转换得到的IP字符串

失败: NULL

// 点分十进制IP -> 大端整形
in_addr_t inet_addr (const char *cp);

// 大端整形 -> 点分十进制IP
char* inet_ntoa(struct in_addr in);

<think>好的,我需要回答用户关于C语言中大小端转换函数的实现和示例的问题。首先,我应该回顾大小端的基本概念,明确它们在内存中的存储方式。大端模式是将高位字节存储在低地址,而小端模式则是高位字节存储在高地址。接下来,用户需要具体的函数实现,所以我得想如何通过C语言代码来交换字节顺序。 首先,考虑一个32位整数的例子,比如0x12345678。大小端转换需要将字节顺序反转。可以通过位操作来实现:使用位移和掩码来提取每个字节,然后重新组合。例如,将原数的第一个字节左移24位,第二个左移16位,第三个左移8位,最后一个不变,然后进行或操作。 然后,我需要提供一个通用的函数,可能使用联合体或者指针来逐字节操作。使用联合体可以方便地访问各个字节,避免类型转换的复杂性。另外,用户可能还需要判断当前系统的字节序,所以需要编写一个检查大小端函数,比如通过检查整数字节的存储位置。 接下来,我需要参考用户提供的引用,特别是引用[3],其中提到了check_endian函数和swap_endian的实现。应该确保示例代码正确,并且有详细的注释,帮助用户理解每一步的操作。同时,需要注意代码的可移植性和效率,比如使用位操作可能比逐字节复制更高效。 最后,生成相关问题时要考虑用户可能进一步想知道的内容,比如性能优化、应用场景和与其他函数的结合使用。确保问题覆盖常见的使用场景和潜在的问题,帮助用户深入理解该主题。</think>### C语言大小端转换函数实现及示例 #### 一、大小端基本概念 大小端(Endianness)指数据在内存中的存储顺序: 1. **大端模式(Big-Endian)**:高位字节存储在低地址,低位字节存储在高地址。例如,整数$0x12345678$在大端系统中存储为:$12\ 34\ 56\ 78$[^3]。 2. **小端模式(Little-Endian)**:低位字节存储在低地址,高位字节存储在高地址。例如,$0x12345678$在小端系统中存储为:$78\ 56\ 34\ 12$[^3]。 --- #### 二、大小端转换函数实现 ##### 1. 使用位操作实现32位整数转换 ```c #include <stdint.h> uint32_t swap_endian(uint32_t value) { return ((value >> 24) & 0x000000FF) | // 提取最高字节并移到最低位 ((value >> 8) & 0x0000FF00) | // 提取次高字节并左移8位 ((value << 8) & 0x00FF0000) | // 提取次低字节并左移16位 ((value << 24) & 0xFF000000); // 提取最低字节并移到最高位 } ``` ##### 2. 使用联合体实现通用转换(支持任意类型) ```c #include <string.h> void swap_endian_generic(void* data, size_t size) { uint8_t* bytes = (uint8_t*)data; for (size_t i = 0; i < size / 2; i++) { uint8_t temp = bytes[i]; bytes[i] = bytes[size - 1 - i]; bytes[size - 1 - i] = temp; } } // 示例:转换64位整数 uint64_t num = 0x123456789ABCDEF0; swap_endian_generic(&num, sizeof(num)); // 结果变为0xF0DEBC9A78563412 ``` ##### 3. 判断当前系统字节序 ```c int check_endian() { union { uint32_t i; uint8_t c[4]; } test = {0x01020304}; return (test.c[0] == 0x01) ? 0 : 1; // 返回0表示大端,1表示小端 } ``` --- #### 三、应用场景 1. **网络协议**:网络传输统一使用大端字节序(如TCP/IP协议)[^3]。 2. **跨平台数据交换**:不同字节序的设备间传输二进制数据。 3. **文件格式解析**:处理特定字节序的文件(如BMP图像头)。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值