C 字节/位的获取,置位,清位操作,大小端转换的宏操作

使用标准库函数C标准库提供了几个函数来处理字节序转换,这些函数通常用于网络编程。它们包括 htons、ntohs、htonl 和 ntohl,分别用于16位和32位整数的转换。对于64位整数,虽然标准库没有直接提供 htonll 和 ntohll 函数,但可以使用 htonl 和 ntohl 来组合实现。

32位整数的转换

#include <stdio.h>
#include <arpa/inet.h> // 包含字节序转换函数

uint32_t htonl_32(uint32_t hostlong) {
    return htonl(hostlong);
}

uint32_t ntohl_32(uint32_t netlong) {
    return ntohl(netlong);
}

64位整数的转换

#include <stdint.h>
uint64_t htonll(uint64_t value) {
    union {
        uint64_t ll;
        uint8_t b[8];
    } n, h;

    n.ll = value;
    h.b[0] = n.b[7];
    h.b[1] = n.b[6];
    h.b[2] = n.b[5];
    h.b[3] = n.b[4];
    h.b[4] = n.b[3];
    h.b[5] = n.b[2];
    h.b[6] = n.b[1];
    h.b[7] = n.b[0];

    return h.ll;
}


uint64_t ntohll(uint64_t value) {
    return htonll(value);
}

手动实现字节序转换

如果你不想依赖于标准库函数,或者需要更通用的解决方案,可以手动实现字节序转换。

32位整数的手动转换

#include <stdint.h>
uint32_t htonl_manual(uint32_t x) {
    return (x >> 24) | ((x & 0x00FF0000) >> 8) | ((x & 0x0000FF00) << 8) | (x << 24);
}

uint32_t ntohl_manual(uint32_t x) {
    return htonl_manual(x); // 大端到小端和小端到大端的转换是相同的
}

64位整数的手动转换

#include <stdint.h>
uint64_t htonll_manual(uint64_t x) {
    return ((x & 0xFF00000000000000ULL) >> 56) |
           ((x & 0x00FF000000000000ULL) >> 40) |
           ((x & 0x0000FF0000000000ULL) >> 24) |
           ((x & 0x000000FF00000000ULL) >> 8)  |
           ((x & 0x00000000FF000000ULL) << 8)  |
           ((x & 0x0000000000FF0000ULL) << 24) |
           ((x & 0x000000000000FF00ULL) << 40) |
           ((x & 0x00000000000000FFULL) << 56);
}

uint64_t ntohll_manual(uint64_t x) {
    return htonll_manual(x); // 大端到小端和小端到大端的转换是相同的
}

示例代码下面是一个完整的示例代码,展示了如何使用上述函数进行32位和64位整数的大端和小端之间的转换。

#include <stdio.h>
#include <stdint.h>
#include <arpa/inet.h> // 包含字节序转换函数

// 32位整数的转换
uint32_t htonl_32(uint32_t hostlong) {
    return htonl(hostlong);
}

uint32_t ntohl_32(uint32_t netlong) {
    return ntohl(netlong);
}

// 64位整数的转换
uint64_t htonll(uint64_t value) {
    union {
        uint64_t ll;
        uint8_t b[8];
    } n, h;

    n.ll = value;
    h.b[0] = n.b[7];
    h.b[1] = n.b[6];
    h.b[2] = n.b[5];
    h.b[3] = n.b[4];
    h.b[4] = n.b[3];
    h.b[5] = n.b[2];
    h.b[6] = n.b[1];
    h.b[7] = n.b[0];

    return h.ll;
}

uint64_t ntohll(uint64_t value) {
    return htonll(value);
}

int main() {
    uint32_t little_endian_32 = 0x12345678;
    uint64_t little_endian_64 = 0x123456789ABCDEF0;

    printf("Little Endian 32-bit: 0x%08X\n", little_endian_32);
    printf("Big Endian 32-bit: 0x%08X\n", htonl_32(little_endian_32));
    printf("Back to Little Endian 32-bit: 0x%08X\n", ntohl_32(htonl_32(little_endian_32)));

    printf("\n");

    printf("Little Endian 64-bit: 0x%016lX\n", (unsigned long long)little_endian_64);
    printf("Big Endian 64-bit: 0x%016lX\n", (unsigned long long)htonll(little_endian_64));
    printf("Back to Little Endian 64-bit: 0x%016lX\n", (unsigned long long)ntohll(htonll(little_endian_64)));

    return 0;
}

输出
Little Endian 32-bit: 0x12345678
Big Endian 32-bit: 0x78563412
Back to Little Endian 32-bit: 0x12345678

Little Endian 64-bit: 0x123456789abcdef0
Big Endian 64-bit: 0xf0debc9a78563412
Back to Little Endian 64-bit: 0x123456789abcdef0
#󠁪# 总结
32位整数:使用 htons、ntohs、htonl 和 ntohl 函数。
64位整数:可以使用联合体或手动位操作来实现 htonll 和 ntohll 函数。
手动实现:通过位移和按位与操作来实现字节序转换。
通过这些方法,你可以轻松地在C语言中进行32位和64位整数的大端和小端之间的转换。

附录 位操作

#include <stdio.h>
#include <stdlib.h>
 
///防止头文件重复包含
#ifdef _HEAD_H_
#define _HEAD_H_
 
///如果C++ 引用,提醒C++编译器用C语言的方式去编译
#ifdef __cplusplus
extern "C"{
#endif
 
 
///对字节操作
#define    GET_LOW_BYTE0(x)    ((x >>  0) & 0x000000ff)    /* 获取第0个字节 */
#define    GET_LOW_BYTE1(x)    ((x >>  8) & 0x000000ff)    /* 获取第1个字节 */
#define    GET_LOW_BYTE2(x)    ((x >> 16) & 0x000000ff)    /* 获取第2个字节 */
#define    GET_LOW_BYTE3(x)    ((x >> 24) & 0x000000ff)    /* 获取第3个字节 */
 
#define    CLEAR_LOW_BYTE0(x)    (x &= 0xffffff00)    /* 清零第0个字节 */
#define    CLEAR_LOW_BYTE1(x)    (x &= 0xffff00ff)    /* 清零第1个字节 */
#define    CLEAR_LOW_BYTE2(x)    (x &= 0xff00ffff)    /* 清零第2个字节 */
#define    CLEAR_LOW_BYTE3(x)    (x &= 0x00ffffff)    /* 清零第3个字节 */
 
#define    SET_LOW_BYTE0(x)  (x |= 0x000000ff)    /* 第0个字节置1 */
#define    SET_LOW_BYTE1(x)  (x |= 0x0000ff00)    /* 第1个字节置1 */
#define    SET_LOW_BYTE2(x)  (x |= 0x00ff0000)    /* 第2个字节置1 */
#define    SET_LOW_BYTE3(x)  (x |= 0xff000000)    /* 第3个字节置1 */
 
 
///对位节操作
#define    GET_BIT(x, bit)    ((x & (1 << bit)) >> bit)    /* 获取第bit位 */
#define    CLEAR_BIT(x, bit)    (x &= ~(1 << bit))        /* 清零第bit位 */
#define    SET_BIT(x, bit)    (x |= (1 << bit))            /* 置位第bit位 */
#define BIT_M_TO_N(x, m, n)  ((unsigned int)(x << (31-(n))) >> ((31 - (n)) + (m)))   /* 获取第[n:m]位的值  eg 第二位到第三位:[2:3] */
 
///大小端转换
// 4bytes、32bit数据大小端转化
#define L2B32(Little) (((Little & 0xff) << 24) | (((Little) & 0xff00) << 8) | (((Little) & 0xff0000) >> 8) | ((Little >> 24) & 0xff))
// 2bytes、16bit数据大小端转化
#define L2B16(Little) (((Little & 0xff) << 8) | ((Little >> 8) & 0xff))
 
 
 
///   u0_Printf/u1_Printf/u2_Printf 三个串口的打印函数,可以自由切打印函数
void (*Printf)(char* fmt,...);
///选择串口
#define  UART   2
 
///选择打印内容
#define  DEBUGALL    0
#define  DEBUGTIME   0
#define  NOTHING     0
 
#if UART == 0
#define Printf   u0_Printf
 
#elif UART == 1
#define Printf   u1_Printf
 
#else
#define Printf   u2_Printf
 
#endif
 
#if DEBUGALL
  #define DBG_PRINTF(fmt, args...)  \
  {\
    Printf("<<File:%s  Line:%d  Function:%s>> ", __FILE__, __LINE__, __FUNCTION__);\
    Printf(fmt, ##args);\
  }
#elif DEBUGTIME
    #define DBG_PRINTF(fmt, args...)  \
    {\
        Printf("<<Time:%s>> ", __TIME__);\
        Printf(fmt, ##args);\
    }
#elif NOTHING
    #define DBG_PRINTF(fmt, args...)  \
    {\
        NOP();\
    }
#else
  #define DBG_PRINTF(fmt, args...)\
    {\
        Printf(fmt, ##args);\
    }
#endif
 
///函数外声明
extern  void DeBug_Init(void);
extern  void DeBug_Task(void);
 
 
#ifdef __cplusplus
};
 #endif
 
#endif _HEAD_H_
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值