首页 > 其他分享 >百度面试真题 - 大小端字节序问题(联合体/共用体 - 面试加分)

百度面试真题 - 大小端字节序问题(联合体/共用体 - 面试加分)

时间:2025-01-15 09:33:56浏览次数:3  
标签:位操作 字节 真题 int 联合体 面试 地址 内存

标题大小端字节序

标题大小端字节序(联合体/共用体)

优质资源


以上bilibili教程(大小端存储 - 详细简介)(空间也有)

目录

​编辑

简介大小端存储(空间视频详解):

强制类型转换 - char*:

巧用联合体,解决百度面试题  -  大小端字节序问题:

使用联合体的优点:


简介大小端存储(空间视频详解):

       a.大小端的定义大端模式(Big - Endian):是指高位字节存放在内存的低地址端,低位字节存放在内存的高地址端。例如一个32位的整数0x12345678,在大端模式下,内存中的存储顺序是:0x12在最低地址处,然后是0x34,接着是0x56,最后0x78在最高地址处。这种存储方式和我们人类阅读数字的习惯比较相似,从高位到低位。

        b.小端模式(Little - Endian):与大端模式相反,高位字节存放在内存的高地址端,低位字节存放在内存的低地址端。还是以0x12345678为例,在小端模式下,内存中的存储顺序是:0x78在最低地址处,然后是0x56,接着是0x34,最后0x12在最高地址处。这种存储方式在计算机系统中也很常见,比如x86架构的处理器就是采用小端模式。

方法一(易,这样的写法在面试要求中,显然相差云泥之别):

#include<iostream>
using namespace std;

int main() {
	int a = 1;//int类型,在内存中的布局

	if (1 == *(char*)(&a))//重点标记:强制转换char*
	{
		cout << "小端存储" << endl;
	}
	else {
		cout << "大端存储" << endl;
	}

	return  0;
}

强制类型转换 - char*:

  1. 字节序(Endianness)

    • 小端序(Little-Endian):低位字节存储在内存的低地址端,高位字节存储在内存的高地址端。
    • 大端序(Big-Endian):高位字节存储在内存的低地址端,低位字节存储在内存的高地址端。
  2. int 类型的内存布局

    • 假设 int 类型占用 4 个字节,整数 1 在内存中的表示为 00000001 00000000 00000000 00000000(以 32 位为例)。
    • 在小端序系统中,内存布局为:
      • 地址 0: 01 (低位字节)
      • 地址 1: 00
      • 地址 2: 00
      • 地址 3: 00
    • 在大端序系统中,内存布局为:
      • 地址 0: 00
      • 地址 1: 00
      • 地址 2: 00
      • 地址 3: 01 (高位字节)
  3. 转换为 char*

    • char 类型的大小为 1 字节,因此将 int 类型的地址转换为 char* 类型后,可以逐字节访问 int 类型变量的内存。
    • 通过 *(char*)(&a),我们访问了 int 类型变量 a 的第一个字节(即内存中的低地址字节)。
  4. 检查字节序

    • 如果 *(char*)(&a) 的值为 1,说明 int 类型变量 a 的第一个字节(低地址字节)是 01,这表明系统是小端序。
    • 如果 *(char*)(&a) 的值为 0,说明 int 类型变量 a 的第一个字节(低地址字节)是 00,这表明系统是大端序。

方法二(函数形式,地址传递)

#include<iostream>
using namespace std;

int check_sys(const int* pa)
{
	return *(char*)(pa);

}
int main()
 {
	int a = 1;
	
	int ret = check_sys(&a);

	if (ret == 1) {
		cout << "小端存储" << endl;
	}
	else {
		cout << "大端存储" << endl;
	}
	return  0;
}

难度增加:

#include <iostream>
using namespace std;

unsigned char check_sys(const int* pa)
 {
    return *reinterpret_cast<const unsigned char*>(pa);
 }

int main() {
    int a;
    cout << "请输入一个整数: ";
    cin >> a;

    unsigned char ret = check_sys(&a);

    // 检查输入值的最低字节是否等于返回的字节
    if (ret == (a & 0xFF)) //按位操作
    {
        cout << "小端存储" << endl;
    }
    else 
    {
        cout << "大端存储" << endl;
    }

    return 0;
}

      

  1. 当 a 为随机输入值时

    • 判断大小端的方法需要稍作调整:关键在于检查 a 的最低有效字节(LSB)是否为 1。
      如果 a 的值是 1,那么在小端存储中,最低地址的字节将是 1,而在大端存储中,最低地址的字节将是 0。
              但是,如果 a 是一个随机值,我们需要检查 a 的最低有效字节是否为 1,而不是直接检查 a 是否等于 1。
    • 检查最低有效字节
                 a. a & 0xFF:这将提取 a 的最低有效字节。例如,如果 a 是 0xABCD1234,那么 a & 0xFF 的结果是 0x34。  
                 b. check_sys(&a):调用 check_sys 函数,返回 a 的最低地址字节的值。
      如果 check_sys(&a) 的返回值等于 a & 0xFF,则说明 a 的最低有效字节存储在最低地址,即小端存储。否则,说明 a 的最低有效字节存储在高地址,即大端存储。
  2. 运行示例

    假设用户输入 0xABCD1234:

             a.小端存储:最低地址的字节是 0x34,a & 0xFF 也是 0x34,因此输出 "小端存储"。
             b.大端存储:最低地址的字节是 0xAB,a & 0xFF 是 0x34,因此输出 "大端存储"。

  3. 按位操作的优点:

                 它通过直接操作数据的二进制位来实现各种功能。按位操作的优点主要体现在以下几个方面:

    a. 效率高:
                  硬件层面:按位操作直接在硬件层面进行,通常比其他高级操作(如算术运算、逻辑运算等)更快。这是因为按位操作直接作用于寄存器中的位,不需要复杂的指令序列。
    编译器优化:现代编译器通常会对按位操作进行高度优化,确保它们在运行时非常高效。
    b. 内存使用高效:
                  紧凑的数据表示:按位操作可以将多个布尔值或标志位存储在一个整数中,从而节省内存。例如,一个 int 类型的变量可以存储 32 个布尔标志位。
    减少内存访问:通过按位操作,可以在单个内存访问中处理多个标志位,减少内存访问次数,提高性能。
    c. 控制硬件:
                  低级硬件操作:按位操作常用于低级硬件编程,如嵌入式系统、驱动程序开发等。通过直接操作寄存器的位,可以精确控制硬件设备的状态。
    位掩码和位操作:可以使用位掩码(Bitmask)和位操作来设置、清除、翻转和检查特定的位,这对于硬件寄存器的控制非常有用。
    d. 算法优化:
                  位运算技巧:按位操作可以用于实现一些高效的算法和数据结构,如位图(Bitmap)、布隆过滤器(Bloom Filter)等。快速幂运算:按位操作可以用于实现快速幂运算(Exponentiation by Squaring),在计算大数的幂时非常高效。
    e. 数据压缩:
                  信息编码:按位操作可以用于数据压缩和编码,通过将多个小的数据值合并到一个整数中,减少存储空间。位字段:在结构体中使用位字段(Bit Fields)可以精确控制每个字段的位数,从而节省内存。
    f. 加密和哈希:
                  位混合:按位操作常用于加密算法和哈希函数中,通过位混合(Bit Mixing)和位置换(Bit Permutation)来提高算法的安全性和均匀性。生成随机数:按位操作可以用于生成伪随机数,通过位操作生成具有特定统计特性的随机数序列。
    g. 错误检测和纠正:
                  奇偶校验:按位操作可以用于生成和检查奇偶校验位,用于检测数据传输中的错误。CRC校验:循环冗余校验(CRC)算法中大量使用按位操作,用于检测数据的完整性。
    h. 代码简洁性:
                  简洁的表达:按位操作可以将复杂的逻辑操作简化为几行代码,使代码更简洁、更易读。减少条件语句:通过按位操作,可以减少条件语句的使用,使代码更高效。

巧用联合体,解决百度面试题  -  大小端字节序问题:

(满分联合体,恰到好处):

#include<iostream>
using namespace std;

int check_sys()
{
	/*
代码机理:
	函数 check_sys:

在 check_sys 函数中,创建了一个 union Un 类型的对象 u。
将 u.i 设置为输入的整数 a。
返回 u.c,即 u.i 的第一个字节的值。
	*/

	union Un

	/*
union Un 定义了一个联合体,包含两个成员:char c 和 int i。
这两个成员共享同一块内存。
	*/
	{
		char c;
		int i;
	}u;//创建对象u

	u.i = 1;
	return u.c;
}
int main() {
	int a = 1;

	int ret = check_sys();

	if (1 == ret) {
		cout << "小端存储" << endl;
	}
	else {
		cout << "大端存储" << endl;
	}
	return  0;
}



#include<iostream>
using namespace std;

int check_sys(int* pa)
{
	union Un//(当然此处也可省略Un),形参匿名联合体类型
	
	{
		char c;
		int i;
	}u;

	u.i = *pa; //使用传入的地址解引用得到所需值
	return u.c;
}
int main() {
	int a = 1;
	cin >> a;
	int ret = check_sys(&a);

	if (ret == (a & 0xFF))//按位操作
	{
		cout << "小端存储" << endl;
	}
	else {
		cout << "大端存储" << endl;
	}
	return  0;
}

使用联合体的优点:

        使用联合体(union)来检测系统的字节序(大小端)是一种非常巧妙且高效的方法。联合体的优点在于它的多个成员共享同一块内存,这意味着对任何一个成员的写操作都会影响到其他成员。这种特性使得联合体成为检测字节序的理想工具。

  1. 内存共享

    • 联合体的所有成员共享同一块内存。
    • 这意味着当你修改其中一个成员时,其他成员的值也会相应改变。这使得联合体非常适合用于检查内存布局,如字节序检测。
  2. 简洁高效

    • 使用联合体可以非常简洁地实现字节序检测,无需复杂的指针操作或类型转换。
    • 代码更易读、易懂。
  3. 类型安全

    • 虽然联合体允许多个不同类型的成员共享内存,但访问联合体的成员时,类型是明确的。
    • 这避免了直接指针操作可能带来的类型安全问题。
  4. 无需外部输入

    • 检测字节序时,通常只需要一个固定的值。
    • 联合体内部就可以完成所有操作,无需从外部获取输入。
  5. 总结

           使用联合体来检测系统的字节序是一种非常简洁、高效且类型安全的方法。联合体的内存共享特性使得它非常适合用于这种类型的检测,无需复杂的指针操作或类型转换。通过上述示例,你可以看到联合体在字节序检测中的强大功能和简洁性。

标签:位操作,字节,真题,int,联合体,面试,地址,内存
From: https://blog.csdn.net/2401_87692970/article/details/145126115

相关文章

  • 案例分析:子词嵌入从字节编码以保护隐私的技术(SEB)的实际应用
    案例分析:子词嵌入从字节编码以保护隐私的技术(SEB)的实际应用简介:在本文中,我们将深入探讨一个创新且极具前景的技术领域,子词嵌入从字节编码(SubwordEmbeddingsfromByte-Coding,简称SEB)。此技术主要用于文本处理,尤其是在需要保护个人隐私的场合下,它提供了独特的解决方案以提升......
  • 算法面试准备 - 手撕系列第二期 - 交叉熵损失(Cross Entropy Loss)
    算法面试准备-手撕系列第二期-交叉熵损失(CrossEntropyLoss)目录算法面试准备-手撕系列第二期-交叉熵损失(CrossEntropyLoss)交叉熵原理图交叉熵损失实现代码-不同y_pre版本参考交叉熵原理图Softmax原理图交叉熵损失实现代码-不同y_pre版本......
  • 常见的软件测试经典面试题
    作为一名软件测试人员,面试不仅是展示技术能力的机会,更是脱颖而出的关键环节。无论你是新手还是资深测试工程师,面试中总会遇到那些“经典题目”。今天,我们就来盘点常见的软件测试经典面试题,帮你提前备战,稳步拿下offer!软件测试面试中,哪些问题经常被问到?如何用专业又简洁的回......
  • 软件测试经典面试题
    ......
  • 中国科学院大学2025年数学分析考研真题
     中国科学院大学2025年数学分析考研真题1.(25分)计算下列极限.(1)$\displaystyle\lim_{x\to1}x^{\frac1{1-x}}$.(2)$\displaystyle\lim_{n\to\infty}\frac{1}{n^{4}}\left(1+2^{3}+\cdots+n^{3}\right)$.2.用闭区间套定理证明$[0,1]$不可数. 3.设$f(x)$在$[0,1]$上连......
  • 20250114面试鸭特训营第22天
    更多特训营笔记详见个人主页【面试鸭特训营】专栏2501141.TCP/IP四层模型是什么?TCP/IP四层模型是一个基于实际网络通信的分层协议模型,主要用于描述互联网通信协议的体系结构。它将网络通信过程分为四个层次,分别为:网络接口层、互联网层(网络层)、传输层、应用层。网络......
  • 华为OD上机考试真题(Java)——排队游戏
    题目:新来的老师给班里的同学排一个队,每个学生有一个能力值。一些学生是刺头,不会听老师的话,自己选位置;非刺头同学在剩下的位置按照能力值从小到大排。对于非刺头同学,如果发现他前面有比自己高的同学,他不满程度就增加,增加的数量等于前面能力值比他大的同学的个数。刺头不......
  • 【程序猿面试真题——计算机基础知识和编程】回调函数怎么实现?
    【程序猿面试真题——计算机基础知识和编程】回调函数怎么实现?【程序猿面试真题——计算机基础知识和编程】回调函数怎么实现?文章目录【程序猿面试真题——计算机基础知识和编程】回调函数怎么实现?什么是回调函数?回调函数的应用场景:回调函数的实现1.回调函数的基本结......
  • 【C语言】_指针面试题
    目录1.示例12.示例23.示例34.示例45.示例56.示例67.示例71.示例1#include<stdio.h>intmain(){ inta[5]={1,2,3,4,5}; int*ptr=(int*)(&a+1); printf("%d,%d",*(a+1),*(ptr-1)); return0;}运行结果如下:分析:(1)a=&a[0],a+......
  • Java Dubbo 面试题
    谈谈你理解的Dubbo?Dubbo是一个高性能的JavaRPC框架,它提供了服务的注册、发现、调用以及监控等功能,使得开发者可以方便地构建分布式系统和服务化架构。服务治理:Dubbo提供了一套服务治理的解决方案,包括服务的注册、发现、负载均衡、容错和监控等。高性能:Dubbo支持多种协议,如Du......