首页 > 其他分享 >C语言:大小端模式、判断大小端、大小端转换

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

时间:2024-09-02 20:55:18浏览次数:10  
标签:little 转换 字节 int C语言 char 内存 endian 大小

目录

1. 什么是大端和小端

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

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

3.1 使用联合体 (union)

3.2 使用指针

3.3 强制转为 char 类型法

4. 大小端转换


1. 什么是大端和小端

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

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

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

简单记忆:

大端模式:大高低

小端模式:小低低

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

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;	// 匿名联合体

#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. 编写大小端转化函数,并打印本机字节序下的数字:0x11223344,分别在小端模式和大端模式下是什么数据。

#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 = 0x11223344;
	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);
}

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),即数据的高字节在内存的高地址存放,数据的低字节在内存的低地址存放。

标签:little,转换,字节,int,C语言,char,内存,endian,大小
From: https://blog.csdn.net/d704791892/article/details/141787687

相关文章

  • 多字节字符串和宽字节字符串相互转换
    #define_CRT_SECURE_NO_WARNINGS/*多字节转宽字节*/intunsafe_mbstowcs(){//设置当前的locale为用户环境变量指定的localesetlocale(LC_ALL,"");//定义多字节字符串constchar*mbstr="Hello,世界!";//计算需要的缓冲区大小size_......
  • 行转列,值转换成列
      1.值转换成列操作。值转列操作:[1777题库] 表:Products+-------------+---------+|ColumnName|Type|+-------------+---------+|product_id|int||store|enum||price|int|+-------------+---------+在SQL中,(prod......
  • C语言_扫雷
    引言:当我们C语言学习完数组的时候,可以尝试一些小的游戏来提升自己,比如下面的这个扫雷。玩法介绍:我们需要在棋盘中选中地雷以外的安全区域,直到最后剩下全部的地雷为止,即可获胜。技能要求:分支语句以及循环语句、函数、数组。接下来我将创建三个文件:具备函数声明、宏定义、......
  • c语言编译器IDE的6键钢琴程序代码
    #include<stdio.h>#include<SDL2/SDL.h>#include<SDL2/SDL_mixer.h>//FunctionforloadingmusictoMix_MusicstaticMix_Music*loadMusic(constchar*path){Mix_Music*music=Mix_LoadMUS(path);if(music==NULL){fprintf(stderr,“M......
  • c语言编译器IDE小钢琴程序代码
    #include<stdio.h>#include<SDL2/SDL.h>#include<SDL2/SDL_mixer.h>//FunctionforloadingmusictoMix_MusicstaticMix_Music*loadMusic(constchar*path){Mix_Music*music=Mix_LoadMUS(path);if(music==NULL){fprintf(stderr,“M......
  • Apache SeaTunnel 2.3.7发布:全新支持大型语言模型数据转换
    我们欣喜地宣布,ApacheSeaTunnel2.3.7版本现已正式发布!作为一个广受欢迎的下一代开源数据集成工具,ApacheSeaTunnel一直致力于为用户提供更加灵活、高效的数据同步和集成能力。此次版本更新不仅引入了如LLM(大型语言模型)数据转换支持、增强的SQL支持和新连接器支持等多个新......
  • C语言指针(进阶内容)
    目录1.指针的基本概念:2.不同类型的指针的意义是什么?3.野指针是什么?4.指针加减整数 5.指针运算(指针-指针)6.一级指针和二级指针以及多级指针是什么意思?7.指针数组8.数组指针9.函数指针1.指针的基本概念:1.指针就是个变量,用来存放地址,地址唯一标识一块内存空......
  • 【树莓派开发】使用树莓派在Linux环境下编写C语言代码
    文章目录前言1.创建test.c文件2.编译运行该文件3.编译并链接两个源文件结语前言如何使用树莓派编译C语言代码呢?21年暑假的时候,学习编程的劲头高涨,然后冲动消费买了个树莓派4B……结果压根不会用,吃灰了半年不过现在已经学完了C语言,也接触了一丢丢Linux系统下的gcc指令,可以尝试用它......
  • 【C语言】文件操作(详解)
    文章目录1.为什么需要文件?2.什么是文件?2.1文件分类2.2文件名3.文件的使用3.1文件指针3.2打开和关闭文件3.2.1文件使用方式3.2.2标准输入输出流3.3文件输入输出函数3.3.1字符输入输出实现文件拷贝3.3.2文本行输入输出3.3.3格式化输入输出3.3.4二进制输入输出3.3.5sscanf/sprintf函......
  • 【C语言】顺序表详解,灵活运用所学知识
    文章目录前言1.什么是顺序表?1.1线性表2.编写你的顺序表!2.0赛前准备2.1初始化2.2容量检查2.3打印顺序表2.4尾插和尾删2.5头插和头删2.6插入和删除2.7查找和更改3.菜单一些err总结前言顺序表是我们学习数据结构第一阶段的必经之路什么是顺序表,且听我慢慢道来本篇博客用到的......