首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >C语言大小端格式详解

C语言大小端格式详解

作者头像
一个平凡而乐于分享的小比特
发布2026-02-02 16:32:03
发布2026-02-02 16:32:03
600
举报

🔥作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生,研究方向无线联邦学习 🎬擅长领域:驱动开发,嵌入式软件开发,BSP开发 ❄️作者主页:一个平凡而乐于分享的小比特的个人主页 ✨收录专栏:c语言重要知识点总结,本专栏旨在总结C语言学习过程中的易错点,通过调试代码,分析原理,对重要知识点有更清晰的理解 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖

在这里插入图片描述
在这里插入图片描述

C语言大小端格式详解

一、什么是大小端格式

大小端指的是多字节数据在内存中的存储顺序。

1. 小端格式 (Little Endian)
  • 低字节存放在低地址
  • 高字节存放在高地址
  • 像Intel x86/x64、ARM(默认)使用小端
代码语言:javascript
复制
#include <stdio.h>

int main() {
    int num = 0x12345678;  // 十六进制数
    unsigned char *p = (unsigned char *)#
    
    printf("值: 0x%x\n", num);
    printf("内存布局(低地址->高地址):\n");
    
    for(int i = 0; i < sizeof(int); i++) {
        printf("地址 %p: 0x%x\n", p+i, *(p+i));
    }
    
    return 0;
}

在小端机器上输出:

代码语言:javascript
复制
值: 0x12345678
内存布局(低地址->高地址):
地址 0x7ffe...: 0x78  // 最低字节
地址 0x7ffe...: 0x56
地址 0x7ffe...: 0x34
地址 0x7ffe...: 0x12  // 最高字节
2. 大端格式 (Big Endian)
  • 高字节存放在低地址
  • 低字节存放在高地址
  • 像PowerPC、网络字节序使用大端
代码语言:javascript
复制
// 假设在大端机器上运行上述代码,输出为:
值: 0x12345678
内存布局(低地址->高地址):
地址 0x7ffe...: 0x12  // 最高字节
地址 0x7ffe...: 0x34
地址 0x7ffe...: 0x56
地址 0x7ffe...: 0x78  // 最低字节

二、如何检测大小端

方法1:使用联合体
代码语言:javascript
复制
#include <stdio.h>

union EndianTest {
    int i;
    char c[sizeof(int)];
};

int isLittleEndian() {
    union EndianTest test;
    test.i = 1;
    return test.c[0] == 1;  // 如果最低地址字节是1,则是小端
}

int main() {
    if (isLittleEndian()) {
        printf("这是小端机器\n");
    } else {
        printf("这是大端机器\n");
    }
    return 0;
}
方法2:使用指针
代码语言:javascript
复制
int isLittleEndian() {
    int num = 1;
    return *(char *)&num == 1;
}

三、字节序转换函数

网络编程中经常需要转换:

代码语言:javascript
复制
#include <arpa/inet.h>  // Linux
// 或 #include <winsock2.h>  // Windows

uint32_t htonl(uint32_t hostlong);   // 主机->网络(32位)
uint16_t htons(uint16_t hostshort);  // 主机->网络(16位)
uint32_t ntohl(uint32_t netlong);    // 网络->主机(32位)
uint16_t ntohs(uint16_t netshort);   // 网络->主机(16位)

// 示例:
uint32_t host_value = 0x12345678;
uint32_t network_value = htonl(host_value);  // 转换为网络字节序

四、什么情况下使用哪种格式

使用小端格式的情况:
  1. x86/x64架构的CPU(Intel、AMD)
  2. ARM处理器(默认小端,可切换)
  3. Windows/Linux桌面系统
  4. 多数嵌入式系统
  5. 本地数据存储(当不需要跨平台时)

优点:

  • 数学运算方便(从低字节开始处理)
  • 类型转换简单
使用大端格式的情况:
  1. 网络协议(TCP/IP规定使用大端)
  2. PowerPC架构
  3. 某些旧版SPARC、MIPS系统
  4. Java虚拟机内部(大端)
  5. 图像文件格式(如BMP、JPEG)
  6. 某些硬件设备的寄存器

优点:

  • 人类阅读友好(与书写顺序一致)
  • 容易判断数值正负(符号位在最低地址)

五、实际应用示例

示例1:网络数据包解析
代码语言:javascript
复制
#include <stdio.h>
#include <stdint.h>

// 模拟从网络接收的数据(大端格式)
void parseNetworkPacket(const uint8_t *packet) {
    // 前4字节是大端的IP地址
    uint32_t ip = (packet[0] << 24) | 
                  (packet[1] << 16) | 
                  (packet[2] << 8) | 
                  packet[3];
    
    // 使用ntohl转换成本机字节序
    ip = ntohl(*(uint32_t*)packet);  // 更标准的做法
    
    printf("IP地址: %u.%u.%u.%u\n", 
           (ip >> 24) & 0xFF,
           (ip >> 16) & 0xFF,
           (ip >> 8) & 0xFF,
           ip & 0xFF);
}
示例2:文件格式处理
代码语言:javascript
复制
// 读取BMP文件头(大端格式)
#pragma pack(push, 1)
typedef struct {
    uint16_t signature;     // "BM",大端
    uint32_t fileSize;      // 大端
    uint16_t reserved1;
    uint16_t reserved2;
    uint32_t dataOffset;    // 大端
} BMPHeader;
#pragma pack(pop)

void readBMP(const char *filename) {
    FILE *file = fopen(filename, "rb");
    BMPHeader header;
    fread(&header, sizeof(header), 1, file);
    
    // 转换字节序
    header.signature = ntohs(header.signature);
    header.fileSize = ntohl(header.fileSize);
    header.dataOffset = ntohl(header.dataOffset);
    
    fclose(file);
}

六、编写跨平台代码的建议

  1. 使用标准转换函数(htonl/ntohl等)
  2. 避免直接内存拷贝不同字节序的数据
  3. 明确数据格式在文档中说明
  4. 测试时考虑字节序
  5. 使用固定宽度整数类型(uint8_t, uint32_t等)
代码语言:javascript
复制
// 安全的字节序无关的读取
uint32_t readUint32BigEndian(const uint8_t *buffer) {
    return (buffer[0] << 24) | 
           (buffer[1] << 16) | 
           (buffer[2] << 8) | 
           buffer[3];
}

uint32_t readUint32LittleEndian(const uint8_t *buffer) {
    return buffer[0] | 
           (buffer[1] << 8) | 
           (buffer[2] << 16) | 
           (buffer[3] << 24);
}

总结

  • 小端:低字节在低地址,常见于Intel CPU
  • 大端:高字节在低地址,用于网络和某些硬件
  • 网络通信必须使用大端
  • 本地存储通常使用本机字节序
  • 跨平台开发要注意字节序转换

理解大小端对网络编程、文件格式解析、硬件交互等至关重要!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2026-01-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • C语言大小端格式详解
    • 一、什么是大小端格式
      • 1. 小端格式 (Little Endian)
      • 2. 大端格式 (Big Endian)
    • 二、如何检测大小端
      • 方法1:使用联合体
      • 方法2:使用指针
    • 三、字节序转换函数
    • 四、什么情况下使用哪种格式
      • 使用小端格式的情况:
      • 使用大端格式的情况:
    • 五、实际应用示例
      • 示例1:网络数据包解析
      • 示例2:文件格式处理
    • 六、编写跨平台代码的建议
    • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档