C语言:大小端模式、判断大小端、大小端转换

C语言:大小端模式、判断大小端、大小端转换对于一个存储空间大于 1 个字节的数据 在内存中有两种存储模式 大端模式 big endian 数据的高字节在内存的低地址存放 数据的低字节在内存的高地址存放小端模式 little endian

大家好,欢迎来到IT知识分享网。

目录

1. 什么是大端和小端

2.为什么会存在大小端的问题

3. 判断主机字节序 (主机大小端)

3.1 使用联合体 (union)

3.2 使用指针

3.3 强制转为 char 类型法

4. 大小端转换


1. 什么是大端和小端

对于一个存储空间大于 1 个字节的数据,在内存中有两种存储模式,

大端模式 (big-endian):数据的高字节在内存的低地址存放,数据的低字节在内存的高地址存放

小端模式 (little-endian):数据的高字节在内存的高地址存放,数据的低字节在内存的低地址存放

简单记忆:

大端模式:大高低

小端模式:小低低

比如,比如数字:0x,大小端存储模式如下:

C语言:大小端模式、判断大小端、大小端转换C语言:大小端模式、判断大小端、大小端转换

2.为什么会存在大小端的问题

        在 C 语言中,有占 1 个字节内存空间的 char 类型,占 2 个字节内存空间的 short int 类型,以及占 4 个字节内存空间的 int,double 类型和占 8 个字节内存空间的 double 类型等等,那么对于大于 1 个字节空间的数据类型的数据在内存中存储时,就必然产生一个数据在内存中应该将其低字节数据安排在内存的低地址还是高地址呢?,对这个问题做的不同选择,就形成了大小端问题。

3. 判断主机字节序 (主机大小端)

3.1 使用联合体 (union)

        联合体的每一个成员共用一个内存地址,修改其中一个成员的数据,可能会影响其它成员的数据的值。比如以下联合体,成本变量 i 和 c 的内存地址是相同的,它的内存分布示意图为

 union { int i; char c; }un; // 匿名联合体

C语言:大小端模式、判断大小端、大小端转换

#include <stdio.h> int is_little_endian() { union { int i; char c; }un; // 匿名联合体 un.i = 1; return un.c; // 小端:返回 1,说明数据的低字节在内存的低地址存放 // 大端:返回 0,说明数据的低字节在内存的高地址存放 } int main() { if (is_little_endian()) printf("little-endian\n"); else printf("big-endian\n"); return 0; }

3.2 使用指针

#include <stdio.h> int is_little_endian() { int i = 1; // 等同于 char* p = (char*)&i; return *p; return *(char*)&i; // 小端:返回 1,说明数据的低字节在内存的低地址存放 // 大端:返回 0,说明数据的低字节在内存的高地址存放 } int main() { if (is_little_endian()) printf("little-endian\n"); else printf("big-endian\n"); return 0; }

3.3 强制转为 char 类型法

#include <stdio.h> int is_little_endian() { int i = 1; // (char)i : 强转为 char 类型,实际就是取 i 在内存中第一个字节的数据 return (char)i; // 小端:返回 1,说明数据的低字节在内存的低地址存放 // 大端:返回 0,说明数据的低字节在内存的高地址存放 } int main() { if (is_little_endian()) printf("little-endian\n"); else printf("big-endian\n"); return 0; }

4. 大小端转换

        1. 编写大小端转化函数,并打印本机字节序下的数字:0x,分别在小端模式和大端模式下是什么数据。

#include <stdio.h> int is_little_endian(); int to_opposite_endian(int data); int to_big_endian(int data); int to_little_endian(int data); int main() { int i = 0x; printf("little_endian: %x\n", to_little_endian(i)); printf("big_endian: %x\n", to_big_endian(i)); return 0; } int is_little_endian() { int i = 1; return (char)i; // 小端:返回 1,大端:返回 0 } // 大小端转换 int to_opposite_endian(int data) { int size = sizeof(data); int des = 0; // 目标数据 int mask = 0xff; // 掩码 int temp; for (int i = 0; i < size; i++) { des = des << 8; // 左移8位 temp = data & mask; // 取值 temp = temp >> i * 8; // 移到低8位 des |= temp; mask = mask << 8; // 掩码左移8位,为下一次取数据用 } return des; } int to_big_endian(int data) { if (!is_little_endian()) // 大端 return data; return to_opposite_endian(data); } int to_little_endian(int data) { if (is_little_endian()) // 小端 return data; return to_opposite_endian(data); }

C语言:大小端模式、判断大小端、大小端转换

2. 在网络编程中,可以使用 htonl, htons, ntohl, ntohs 等函数

  • htonl(uint32_t hostlong) // host to network long,32位无符号整型的主机字节序转成网络字节序
  • htons(uint16_t hostshort) // host to network short,16位无符号短整型的主机字节序转成网络字节序
  • ntohl(uint32_t netlong) // network to host long,32位无符号整型的网络字节序转成主机字节顺序的
  • ntohs(uint16_t netshort) //16位无符号短整型的网络字节序转成主机字节序

网络字节序:大端模式(big-endian),即数据的高字节在内存的高地址存放,数据的低字节在内存的低地址存放。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/114300.html

(0)
上一篇 2025-12-09 15:26
下一篇 2025-12-09 15:45

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信