当前位置: 首页 > news >正文

嵌入式八股文之 struct 和 union 的区别、大厂真题1、头文件中的#ifdef/#define/#endif作用是什么?

一、struct (结构体) 和 union (联合体) 的区别

(1) 在存储多个成员信息时,编译器会自动给 struct 每个成员分配存储空间,strcut 可以存储多个成员信息,而 Union 每个成员会用同一个存储空间,大小为最大成员的大小。

(2) 都是由多个不同的数据类型成员组成,但在任何同一时刻,Union 只存放了一个被先选中的成员,而结构体的所有成员都存在。

(3) 对于 Union 的不同成员赋值,将会对其他成员重写,原来成员的值就不存在了,而对于 struct 的不同成员赋值是互不影响的

二、大厂真题

请写出 printf 的值(基于小端序)

#include <stdio.h>int main() {union {int i;struct {char first;char second;} half;} number;number.i = 0x4241;printf("%c%c\n", number.half.first, number.half.second); // 输出:ABnumber.half.first = 'a';number.half.second = 'b';printf("%x\n", number.i); // 输出:6261(十六进制)return 0;
}

解:本道题设计了计算机组成原理、操作系统、嵌入式系统开发、网络编程

1. 十六进制转换为十进制

(1) 0x 是一个前缀标识符,用于明确表示后面的数字是十六进制表示法。

(2) 记忆转换表:

十六进制十进制
0x00
0x11
0x22
0xA10(A 代表了10)
0xB11(B 代表了11)
0xC12
0xD13
0xE14
0xF15
0x1016(正好是十六进制)
0xFF255

(3) 0x4241 的十进制换算:

0x4241 = 4 × 16³ + 2 × 16² + 4 × 16¹ + 1 × 16⁰

2. ASCII 表

字符ASCII 十进制
A65
B66
C67
a97
b98
c99

3. 代码说明:

(1) 联合体定义:

union {int i;  // 4字节整型(平台相关,通常4字节)struct {char first;  // 1字节字符char second; // 1字节字符} half;          // 共占2字节
} number;
  • 联合体 number 包含两个成员:整型 i(4字节)和结构体 half(2字节)
  • 小端序:低位数据存储在低地址

(2) 写入整型 i 并读取字符

number.i = 0x4241; // 十六进制赋值
printf("%c%c\n", number.half.first, number.half.second); // 输出:AB

① 内存布局:

内存地址低地址 → 高地址
值(十六进制)0x41
对应成员first

② 解析:

  • 0x41 是字符 'A' 的 ASCII 码,0x42 是 'B'
  • 因此 first 读取到 0x41 ('A'),second 读取到 0x42('B'),输出 AB

(3) 写入字符并读取整型 i

number.half.first = 'a'; // ASCII 0x61
number.half.second = 'b'; // ASCII 0x62
printf("%x\n", number.i); // 输出:6261(十六进制)

① 整型 i 的值(小端序):

  • 内存低位到高位 0x61,0x62,0x00,0x00 → 拼合为 0x000006261

② 数据拼合过程:(计算机以 字节 为基本存储单位,每个字可表示的数值范围是 0-255(共 256 种可能)

内存地址:  低 ────────────────▶ 高
字节值:  0x61    0x62    0x00    0x00
权重:    256^0     256^1     256^2    256^3 

计算整数值:

(0x61 × 256⁰) + (0x62 × 256¹) + (0x00 × 256²) + (0x00 × 256³)
= (97 × 1) + (98 × 256) + (0 × 65536) + (0 × 16777216)
= 97 + 25088 
= 25185 

转换为十六进制

25185 (十进制) = 6261 (十六进制)

  • 反复除以 16:用十进制数连续除以 16,记录每次的余数
  • 余数转16 进制:余数 0-9 保持原数字,10-15 转为字母 A-F
  • 逆序排列:最后得到的余数数列反向排列
  • 添加前缀:结果前加 0x

(4) 答案:

AB

6261

三、头文件中的 #ifdef/#define/#endif 作用是什么? 

1. 核心目的是防止头文件重复包含:避免同一个头文件被多次 #include 时出现重复声明/定义错误

2. 条件编译控制:根据宏是否定义,决定编译哪些代码

3. 跨平台支持:为不同平台编译不同代码

http://www.xdnf.cn/news/1165087.html

相关文章:

  • React探索高性能Tree树组件实现——react-window、react-vtree
  • Kafka 如何优雅实现 Varint 和 ZigZag 编码
  • AXI接口学习
  • 在github上搭建自己主页
  • Spring Boot 3核心技术面试指南:从迁移升级到云原生实战,9轮技术攻防(含架构解析)
  • 添加状态信息
  • Linux find命令:强大的文件搜索工具
  • 代码审计Tabby安装教程
  • 神经网络——归一化层
  • nextjs编程式跳转
  • LinkedList的模拟实现(双向链表Java)
  • Java注解家族--`@ResponseBody`
  • 神经网络——线性层
  • 【c++】leetcode5 最长回文子串
  • 蚂蚁数科AI数据产业基地正式投产,携手苏州推进AI产业落地
  • 奥比中光深度相机开发
  • 感知机-梯度下降法
  • 141 个 LangChain4j Maven 组件分类解析、多场景实战攻略
  • 一个月掌握数据结构与算法:高效学习计划
  • hot100回归复习(算法总结1-38)
  • 零拷贝技术(Zero-Copy)
  • 网络协议(四)网络层 路由协议
  • C++基于libmodbus库实现modbus TCP/RTU通信
  • 大模型——上下文工程 (Context Engineering) – 现代 AI 系统的架构基础
  • C# 实现:动态规划解决 0/1 背包问题
  • iOS开发 Swift 速记2:三种集合类型 Array Set Dictionary
  • OCR 身份识别:让身份信息录入场景更高效安全
  • 如何使用终端查看任意Ubuntu的版本信息
  • 用 Three.js 实现 PlayCanvas 风格 PBR 材质教程(第二篇):核心参数与光照模型
  • DBSCAN聚类算法