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

嵌入式面试题解析:常见基础知识点详解

在嵌入式领域的面试中,基础知识点的考察尤为重要。下面对一些常见面试题进行详细解析,帮助新手一步步理解。

一、原码、反码、补码及补码的好处

题目

什么叫原码、反码、补码?计算机学科引入补码有什么好处?

在计算机科学中,原码、反码和补码是对数字的二进制定点表示方法,它们在嵌入式系统的数据处理和运算中扮演着重要角色。下面我们一步步来详细了解。

1. 原码

原码是一种简单直观的机器数表示法,最高位为符号位,0 表示正数,1 表示负数,其余位表示数值的绝对值。

示例
假设使用 8 位二进制表示数字:

  • 对于 +5,其原码为:

    plaintext

    00000101  
    

    解释:最高位 0 表示正数,后面 00000101 是 5 的二进制表示(22+20=4+1=5)。
  • 对于 −5,其原码为:

    plaintext

    10000101  
    

    解释:最高位 1 表示负数,后面 00000101 同样是 5 的二进制表示。

2. 反码

  • 正数的反码与原码相同。
  • 负数的反码是在原码的基础上,符号位保持不变,其余各位取反(0 变 11 变 0)。

示例

  • +5 的反码:

    plaintext

    00000101 (与原码相同)  
    

    解释:正数的反码规则,直接与原码一致。
  • −5 的原码是 10000101,其反码为:

    plaintext

    11111010  
    

    解释:符号位 1 不变,其余位 00000101 取反,得到 11111010

3. 补码

  • 正数的补码与原码相同。
  • 负数的补码是在反码的基础上,最后一位加 1

示例

  • +5 的补码:

    plaintext

    00000101 (与原码相同)  
    

    解释:正数的补码规则,与原码一致。
  • −5 的反码是 11111010,其补码为:

    plaintext

    11111011  
    

    解释:在反码 11111010 的基础上,最后一位加 1,即 11111010 + 1 = 11111011

4. 计算机学科引入补码的好处

在计算机中引入补码,主要有以下重要好处:

  • 简化运算电路:可以将减法运算转换为加法运算。在计算机硬件中,加法电路相对简单,这样能节省硬件资源,降低设计复杂度。例如计算 5−3,可以转化为 5+(−3),利用补码进行加法运算。
  • 统一处理符号位和数值位:补码使得符号位和数值位能够一起参与运算,无需对符号位进行特殊处理,简化了运算过程。

示例:计算 5−3

  • 5 的补码:00000101
  • −3 的原码:10000011,反码:11111100,补码:11111101
  • 进行加法运算:00000101 + 11111101 = 100000010
    解释:由于是 8 位二进制数,最高位 1 溢出(超出 8 位表示范围),舍去后结果为 00000010,即十进制的 2,计算结果正确。通过补码,将减法 5−3 转化为加法 5+(−3) 进行计算,体现了补码在简化运算上的优势。

通过以上详细的步骤和示例,我们对原码、反码、补码以及补码的好处有了更清晰的认识。这些知识是嵌入式系统中数据表示和运算的基础,理解它们对于后续深入学习嵌入式编程和硬件交互至关重要。

二、大端模式与小端模式

题目

在数据存储中,什么叫大端模式,什么叫小端模式?

在数据存储中,大端模式和小端模式是两种不同的字节存储顺序,其核心区别在于多字节数据的高字节低字节在内存中的存放位置。理解这一概念需要先明确数据的 “高位 / 低位” 和 “高字节 / 低字节” 定义。

1. 前置知识:如何分辨高位、低位、高字节、低字节
(1)位(Bit)的高位与低位

一个字节(8 位)由右至左(从低位到高位)依次为 bit0(最低位,LSB) 到 bit7(最高位,MSB)

  • 低位(LSB):权重最小的位,例如二进制数 0b1010 中,最右侧的 0 是 bit0(低位)。
  • 高位(MSB):权重最大的位,例如 0b1010 中,最左侧的 1 是 bit7(高位,假设为 8 位数据)。
(2)字节(Byte)的高字节与低字节

对于多字节数据(如 16 位、32 位整数):

  • 高字节(MSB,Most Significant Byte):数值中权重最大的字节。
    例如:32 位十六进制数 0x12345678 拆分为 4 个字节:

    plaintext

    高字节 → 0x12(最高权重)→ 0x34 → 0x56 → 0x78(最低权重)← 低字节  
    
  • 低字节(LSB,Least Significant Byte):数值中权重最小的字节(如上述例子中的 0x78)。

关键结论

  • 高 / 低字节是数据本身的属性,与存储顺序无关;
  • 大端 / 小端模式决定了高 / 低字节在内存中的存储顺序
2. 大端模式(Big-endian)

定义高字节存放在低地址,低字节存放在高地址(高位在前,低位在后)。
示例:以 32 位整数 0x12345678 为例(假设从内存地址 0x00 开始存储):

内存地址存储内容(十六进制)对应字节属性二进制表示(8 位)
0x0012高字节(MSB)00010010
0x0134次高字节00110100
0x0256次低字节01010110
0x0378低字节(LSB)01111000

特点

  • 数据的字节顺序与人类阅读习惯一致(高位在前),例如 0x12345678 按地址递增顺序读取,结果与书写顺序一致。
  • 典型应用:网络传输(TCP/IP 协议规定使用大端模式,又称 “网络字节序”)。
3. 小端模式(Little-endian)

定义低字节存放在低地址,高字节存放在高地址(低位在前,高位在后)。
示例:同样以 32 位整数 0x12345678 为例:

内存地址存储内容(十六进制)对应字节属性二进制表示(8 位)
0x0078低字节(LSB)01111000
0x0156次低字节01010110
0x0234次高字节00110100
0x0312高字节(MSB)00010010

特点

  • 数据的字节顺序与人类阅读习惯相反,但便于硬件处理(如 x86 架构、ARM 的部分模式)。
  • 优势:读取低地址即可快速获取低位数据,适合频繁访问低位的场景(如嵌入式设备的寄存器操作)。
4. 如何判断当前系统的字节序?

在嵌入式开发中,可通过代码检测当前系统使用的字节序:

#include <stdio.h>int check_endian() {int num = 0x12345678;char *p = (char *)&num;return *p; // 小端模式返回0x78,大端模式返回0x12
}int main() {if (check_endian() == 0x78) {printf("Little-endian\n");} else {printf("Big-endian\n");}return 0;
}
5. 嵌入式开发中的注意事项
  • 跨平台通信:若设备 A(大端)与设备 B(小端)通信,需通过 htons()htonl() 等函数进行字节序转换(h表示主机,n表示网络)。
  • 硬件寄存器操作:部分外设寄存器要求按特定字节序访问,需严格遵循芯片手册。
  • 数据解析:读取多字节数据(如传感器输出的 16 位 ADC 值)时,需明确设备的字节序,避免解析错误(例如将 0x1234 误读为 0x3412)。

总结

  • 高 / 低字节是数据本身的属性(高位权重 vs 低位权重),大 / 小端模式是数据在内存中的存储顺序。
  • 大端模式:高字节→低地址,低字节→高地址(符合阅读习惯)。
  • 小端模式:低字节→低地址,高字节→高地址(便于硬件操作)。
    理解这些概念是处理嵌入式系统中数据存储、通信和硬件交互的基础,尤其是在跨平台或多设备协作的场景中,正确处理字节序可避免严重的逻辑错误。

三、关键字 volatile

题目

关键字 volatile 修饰的变量有什么特殊之处?

一、volatile 的定义与核心作用

1. 基础概念

volatile 是 C/C++ 中的一个类型限定符(Type Qualifier),用于告诉编译器:被修饰的变量可能会在编译器无法预知的情况下被修改

  • 核心目的:禁止编译器对变量进行「优化读取」,确保每次访问该变量时都直接从内存中读取最新值,而不是使用寄存器中的缓存副本。
2. 为什么需要 volatile?

编译器为了提高执行效率,可能会对频繁访问的变量进行优化:

  • 若变量值未被显式修改(如通过指针、外设、中断等),编译器会认为其值不变,直接从寄存器读取旧值(而非内存)。
  • volatile 用于「打破这种优化」,强制编译器遵循「每次访问都操作内存」的规则。

二、volatile 的三大典型使用场景

场景 1:操作外设寄存器(嵌入式开发核心场景)

嵌入式设备中,外设寄存器的值由硬件直接控制(如 GPIO、ADC、UART 等),其值可能随时被硬件修改,而非通过程序代码。

  • 例子:控制 LED 亮度的 PWM 寄存器
    // 假设 PWM 寄存器地址为 0x40000000,寄存器值由硬件自动更新(如定时器计数)  
    volatile unsigned int *PWM_REG = (volatile unsigned int *)0x40000000;  int main() {  while (1) {  int duty_cycle = *PWM_REG; // 每次读取都强制从内存获取最新值  // 根据 duty_cycle 执行其他操作  }  
    }  
    
     
    • 关键点:若不加 volatile,编译器可能认为 *PWM_REG 的值不变,直接读取寄存器缓存,导致程序无法获取硬件实时更新的值。
场景 2:多线程 / 中断共享变量

当变量被多个线程(或中断服务程序与主程序)共享时,可能存在「一个线程修改变量,另一个线程未感知」的问题。

  • 例子:中断标志位
    volatile int interrupt_flag = 0; // 标志位被中断服务程序修改  // 主程序循环检测标志位  
    while (interrupt_flag == 0) {  // 等待中断  
    }  
    // 中断服务程序(ISR)中修改标志位  
    void ISR() {  interrupt_flag = 1;  
    }  
    
     
    • 不加 volatile 的风险:编译器可能优化循环为 while (1)(认为 interrupt_flag 未被程序修改),导致主程序卡死。
场景 3:防止编译器优化「看似无意义」的代码

某些场景下,代码需要强制执行(如空循环延时、内存屏障),此时 volatile 可阻止编译器删除无效代码。

  • 例子:空循环延时
    void delay_ms(volatile unsigned int ms) { // ms 加 volatile  while (ms-- > 0) {  ; // 空循环  }  
    }  
    
     
    • 若 ms 不加 volatile,编译器可能优化掉整个循环(认为 ms 未被使用),导致延时失效。

三、volatile 与 const 的对比(面试高频考点)

特性volatileconst
核心作用禁止编译器优化,确保内存可见性禁止程序修改变量(只读属性)
变量可修改性允许被外部因素(硬件、中断等)修改不允许被程序修改(常量)
使用场景外设寄存器、共享变量、中断标志定义常量、保护函数参数 / 返回值
兼容性可与 const 同时使用(如 volatile const不可与 volatile 冲突(无意义)

  • 例子:定义一个「只读且易变」的变量(如硬件版本号寄存器)
    volatile const unsigned int HW_VERSION = 0x1234; // 硬件赋值,程序不可修改,但值可能随硬件更新  
    

四、深入理解:编译器如何处理 volatile 变量?

1. 无 volatile 时的优化(危险行为)

假设变量 x 未被 volatile 修饰:

int x = 0;  
while (x == 0) {  x = read_from_sensor(); // 假设通过指针或硬件修改 x  
}  

  • 编译器可能优化为:
    int x = 0;  
    if (x == 0) { // 仅检测一次,之后使用寄存器缓存值  while (1) {  ; // 死循环  }  
    }  
    

plaintext

- **问题**:若 `read_from_sensor()` 实际修改了内存中的 `x`,但编译器未感知,导致循环无法退出。  #### 2. 有 volatile 时的强制行为  
当 `x` 被 `volatile` 修饰时,编译器会生成「每次循环都从内存读取 `x`」的代码:  
```c  
volatile int x = 0;  
while (x == 0) {  x = *(volatile int*)0x1000; // 假设传感器寄存器地址为 0x1000  // 或直接读取变量 x 的内存地址  
}  

  • 本质volatile 告诉编译器「这个变量的修改可能发生在你的控制之外,不要假设它的值不变」。

五、面试题常见拓展问题

问题 1:volatile 能保证原子性吗?
  • 答案:不能。
  • 解释volatile 仅确保内存可见性,不保证操作的原子性。例如,对 volatile int x 的赋值 x = 5 可能被拆分为「写高字节」和「写低字节」两步,多线程下仍需加锁或使用原子操作。
问题 2:哪些情况下必须使用 volatile?
  • 必答场景
    1. 操作外设寄存器(如嵌入式设备的硬件控制寄存器)。
    2. 共享变量被中断服务程序修改(如中断标志位)。
    3. 多线程环境下,变量被多个线程非原子性修改(需配合锁机制)。
问题 3:volatile 对性能有影响吗?
  • 答案:有轻微影响(每次访问内存而非寄存器),但在必要场景(如硬件交互)中不可替代。

六、实战案例:嵌入式代码中的 volatile 应用

假设我们有一个 32 位的 GPIO 输出寄存器 GPIO_OUT,地址为 0x40010000,需要循环输出不同的电平:

// 定义 volatile 指针指向寄存器地址  
volatile unsigned int *GPIO_OUT = (volatile unsigned int *)0x40010000;  int main() {  unsigned int value = 0;  while (1) {  *GPIO_OUT = value; // 每次写操作都直接操作内存(硬件寄存器)  value = (value == 0) ? 1 : 0; // 切换电平  }  
}  

  • 关键点:若不加 volatile,编译器可能优化掉 *GPIO_OUT = value(认为无实际作用),导致硬件无输出。

总结:volatile 的核心价值

volatile 是嵌入式开发中「程序与硬件交互」的桥梁,确保软件能正确感知硬件或外部环境的实时变化。理解其原理需结合编译器优化机制和实际硬件场景,是嵌入式工程师必须掌握的基础关键字。

通过以上解析,新手可逐步掌握 volatile 的定义、使用场景、与其他关键字的区别,以及在嵌入式代码中的具体应用,从容应对面试和实际开发中的相关问题。

四、int 与 unsigned int

题目

  1. int 型变量和 unsigned int 型数据的区别是什么?
  2. 表示的数字范围分别是什么?
  3. 若存在 unsigned int 型变量 a,作 b = (int)a; 的操作后,a 的数据类型是 int 还是 unsigned int

一、核心区别:符号位与存储方式

1. 符号位的存在与否
  • int(有符号整数)
    • 最高位为符号位(0 表示正数,1 表示负数)。
    • 存储方式:使用二进制补码表示(包括符号位和数值位)。
  • unsigned int(无符号整数)
    • 没有符号位,所有位都用于表示数值。
    • 存储方式:使用二进制原码表示(直接存储数值的二进制形式)。

示例:以 8 位数据为例:

数值int 的二进制(补码)unsigned int 的二进制(原码)
50000010100000101
-511111011(补码)不允许存储负数
2. 算术运算特性
  • int
    • 支持正负数的加减乘除运算,运算结果可能溢出为未定义行为(如 INT_MAX + 1 可能变为 INT_MIN)。
  • unsigned int
    • 仅支持非负数运算,溢出时会自动取模(如 UINT_MAX + 1 会变为 0)。

代码示例

int a = INT_MAX;  
a += 1;  // 结果未定义(可能变为 -2147483648)unsigned int b = UINT_MAX;  
b += 1;  // 结果为 0(自动取模 2^32)

二、数字范围:从位宽到实际数值

1. 不同位宽下的范围对比
数据类型位数(位)最小值最大值
int16-3276832767
int32-21474836482147483647
unsigned int16065535
unsigned int3204294967295

关键结论

  • unsigned int 的正数范围是 int 的两倍(因为无需保留符号位)。
  • 实际范围由编译器和硬件决定(如 64 位系统中 int 可能为 32 位或 64 位,需用 sizeof(int) 确认)。
2. 位宽与范围的数学公式
  • int 的范围-2^(n-1) ≤ value ≤ 2^(n-1) - 1n 为位数)。
  • unsigned int 的范围0 ≤ value ≤ 2^n - 1

示例:32 位 int 的范围计算:

  • 最小值:-2^(32-1) = -2147483648
  • 最大值:2^(32-1) - 1 = 2147483647

三、类型转换:强制转换与变量类型

1. 强制转换的本质
  • 语法(type)expression,例如 (int)a
  • 作用:临时将表达式的结果转换为指定类型,不改变原变量的类型

代码验证

unsigned int a = 100;  
int b = (int)a;  // 强制转换为 int  printf("a的类型:%lu字节\n", sizeof(a));  // 输出4字节(unsigned int)
printf("b的类型:%lu字节\n", sizeof(b));  // 输出4字节(int)
2. 转换规则与溢出风险
  • unsigned int → int
    • 若 a ≤ INT_MAX,转换结果为原值。
    • 若 a > INT_MAX,结果为负数(按补码解释)。
  • int → unsigned int
    • 若 a ≥ 0,转换结果为原值。
    • 若 a < 0,结果为 UINT_MAX + a + 1(按无符号数取模)。

示例

unsigned int a = 3000000000;  // 30亿(超过32位int的最大值2147483647)
int b = (int)a;                // b的值为 -1294967296(30亿的补码解释)int c = -6;  
unsigned int d = (unsigned int)c;  // d的值为 4294967290(-6的补码按无符号数解释)

四、隐式转换的陷阱(面试高频考点)

1. 混合运算的类型提升
  • 规则:当 int 和 unsigned int 混合运算时,int 会被隐式转换为 unsigned int
  • 风险:可能导致负数变为大数,引发逻辑错误。

示例

int a = -1;  
unsigned int b = 0;  if (a < b) {  printf("a < b\n");  // 实际执行的是 0xFFFFFFFF < 0 → 条件为假  
} else {  printf("a >= b\n"); // 输出 "a >= b"  
}  
2. 赋值与比较的隐式转换
  • 赋值:右边表达式会转换为左边变量的类型。
    unsigned int x = -1;  // x的值为 0xFFFFFFFF(无符号数的最大值)
    
  • 比较:两个操作数会转换为同一类型(通常是 unsigned int)。
    int i = -1;  
    unsigned int j = 0;  
    if (i == j) {  // 实际比较的是 0xFFFFFFFF == 0 → 条件为假  // 不会执行  
    }  
    

五、使用场景与最佳实践

1. 优先选择 unsigned int 的场景
  • 计数与索引:如数组长度、循环次数(避免负数导致的溢出)。
  • 位操作:如 GPIO 寄存器、协议校验和(无需符号位)。
  • 硬件交互:如嵌入式设备的寄存器地址(硬件不关心符号)。

示例

// 控制LED的循环闪烁次数(使用unsigned int避免负数)
unsigned int led_count = 0;  
while (led_count < 10) {  toggle_led();  led_count++;  
}  
2. 必须使用 int 的场景
  • 需要表示负数:如温度、电压、差值计算。
  • 与标准库函数兼容:如 printf 的返回值、strcmp 的结果。

示例

// 计算温度差值(可能为负)
int temp_diff = current_temp - target_temp;  
if (temp_diff > 5) {  // 执行降温操作  
}  

六、面试题答案总结

  1. 区别

    • int 是有符号整数(最高位为符号位,使用补码存储)。
    • unsigned int 是无符号整数(所有位表示数值,使用原码存储)。
  2. 范围

    • int:32 位时为 -2147483648 ~ 2147483647
    • unsigned int:32 位时为 0 ~ 4294967295
  3. 类型转换

    • 执行 b = (int)a; 后,a 的数据类型仍为 unsigned int,仅表达式 (int)a 的结果为 int 类型。

七、实战案例与避坑指南

案例 1:嵌入式寄存器操作
// 定义32位无符号指针指向GPIO寄存器  
volatile unsigned int *GPIO_REG = (volatile unsigned int *)0x40000000;  // 写入高电平(0xFFFFFFFF)
*GPIO_REG = 0xFFFFFFFF;  
案例 2:循环计数溢出
unsigned int count = 0;  
while (1) {  count++;  if (count == 0) {  // 当count达到UINT_MAX时,下一次递增会变为0  reset_system(); // 触发系统复位  }  
}  
避坑指南
  • 避免混合使用 int 和 unsigned int:优先统一类型,或显式转换。
  • 明确变量用途:用 unsigned int 表示非负数,int 表示可能为负的数值。
  • 使用固定宽度类型:如 uint32_t(C99 标准),避免依赖 int 的平台差异。

通过以上解析,新手可全面掌握 int 与 unsigned int 的核心区别、范围计算、类型转换规则及实战应用,从容应对面试和嵌入式开发中的相关问题。

五、C 语言表达式计算

题目

设 float a = 2, b = 4, c = 3;,以下 C 语言表达式与代数式 (a+b)+c 计算结果不一致的是 ( )。
A. (a + b) * c / 2;
B. (1 / 2) * (a + b) * c;
C. (a + b) * c * 1 / 2;
D. c / 2 * (a + b);

一、代数式与 C 语言表达式的核心差异

1. 代数式的数学计算

(a+b)+c=(2+4)+3=6+3=9

2. 题目隐含修正说明

通过选项分析,题目实际考察的是 代数式 (a+b)×c÷2(可能为笔误,原代数式应为乘除法),以下按正确逻辑解析(若为纯加法,所有选项均与代数式无关,故修正为乘除法场景)。

二、核心考点:数据类型与运算符规则

1. 数据类型影响
  • float 类型a、b、c 均为 float,参与运算时自动触发 浮点运算
  • int 类型:如 1、2 为 int,需注意 整数除法 与 隐式类型转换
2. 运算符优先级
  • * 和 / 优先级相同,按 左结合性 从左到右计算(如 a * b / c = (a * b) / c)。

三、选项逐行解析(关键:类型转换与运算顺序)

选项 A:(a + b) * c / 2
  1. 计算步骤
    • a + b = 2.0 + 4.0 = 6.0float
    • 6.0 * c = 6.0 * 3.0 = 18.0float
    • 18.0 / 2 = 9.02 是 int,隐式转换为 float 后浮点除法)
  2. 结果9.0(与代数式结果一致)
  3. 关键:所有运算均为浮点运算,无整数除法干扰。
选项 B:(1 / 2) * (a + b) * c
  1. 计算步骤
    • 1 / 21 和 2 均为 int,执行 整数除法,结果为 0(C 语言中整数相除向下取整)。
    • 0 * (a + b) = 0 * 6.0 = 0.0float
    • 0.0 * c = 0.0 * 3.0 = 0.0float
  2. 结果0.0(与代数式结果 9.0 不一致,错误根源在此)
  3. 关键整数除法优先执行,导致后续运算基于 0 展开,未触发浮点运算。
选项 C:(a + b) * c * 1 / 2
  1. 计算步骤
    • a + b = 6.0float
    • 6.0 * c = 18.0float
    • 18.0 * 1 = 18.01 是 int,隐式转换为 float
    • 18.0 / 2 = 9.02 隐式转换为 float,浮点除法)
  2. 结果9.0(与代数式结果一致)
  3. 关键:虽然包含 int 类型的 1 和 2,但运算顺序保证了浮点运算的连续性。
选项 D:c / 2 * (a + b)
  1. 计算步骤
    • c / 2c 是 float2 是 int,触发 隐式类型转换2 → 2.0f),结果为 3.0 / 2.0 = 1.5float
    • 1.5 * (a + b) = 1.5 * 6.0 = 9.0float
  2. 结果9.0(与代数式结果一致)
  3. 关键:浮点数与整数混合运算时,整数自动转换为浮点数,确保除法为浮点运算。

四、核心错误:整数除法的陷阱(选项 B 解析)

1. 整数除法规则
  • 当两个 int 类型数据相除时,C 语言执行 截断除法,结果为整数(向下取整),而非数学上的浮点结果。
    int x = 1 / 2; // x 的值为 0(而非 0.5)  
    
  • 若需浮点结果,需至少有一个操作数为浮点数(如 1.0 / 2 或 (float)1 / 2)。
2. 选项 B 错误根源
  • (1 / 2) 未触发浮点运算,导致后续所有乘法基于 0 进行,最终结果错误。

五、隐式类型转换规则(拓展知识)

操作数类型转换规则示例
int + floatint 转换为 float2 + 3.0 = 5.0
int / int整数除法(结果为 int5 / 2 = 2
float / intint 转换为 float,浮点除法5.0 / 2 = 2.5
(int)float显式转换为 int(截断小数部分)(int)2.9 = 2

六、答案与解析

答案:B
解析
选项 B 中 (1 / 2) 是整数除法,结果为 0,导致整个表达式结果为 0,与代数式 (a + b) * c / 2 = 9 的计算结果不一致。其他选项通过浮点运算或隐式类型转换,均得到正确结果 9

七、实战避坑指南

  1. 避免整数除法意外
    • 若需浮点结果,显式转换操作数类型(如 1.0f / 2 或 (float)1 / 2)。

      c

      float result = (float)1 / 2 * (a + b) * c; // 显式转换为 float,结果正确  
      
  2. 复杂表达式加括号
    • 用括号明确运算顺序,避免优先级错误(如 ((a + b) * c) / 2)。
  3. 统一数据类型
    • 涉及浮点数运算时,建议将初始变量定义为 float 类型(如 float a = 2.0f;)。

总结

本题核心考察 C 语言中 整数除法特性 和 隐式类型转换规则。选项 B 的错误在于整数除法导致的截断,而其他选项通过浮点运算或正确的类型转换避免了这一问题。理解这些规则是编写数值计算代码的基础,也是嵌入式开发中处理传感器数据、算法运算的关键能力。通过明确数据类型、合理使用括号和显式类型转换,可以有效避免类似错误。

六、位操作

题目

对于 unsigned 型变量 a,若要对其 bit[7] 做清零、置位、取反操作,分别如何用 1 条语句实现?

一、前置知识:位操作符与掩码构造

1. 关键位操作符
操作符名称作用示例(对 bit[n] 操作)
&按位与清零(与 0 清零,与 1 保留)a &= ~(1 << n) (清零)
``按位或置位(与 1 置位,与 0 保留)`a= (1 << n)` (置位)
^按位异或取反(与 1 翻转,与 0 保留)a ^= (1 << n) (取反)
2. 掩码构造
  • bit[7] 表示从右往左数第 8 位(从 bit[0] 开始计数),对应的二进制掩码为 1 << 7(即 0x80,假设 unsigned 为 8 位)。
  • 对于 16 位 / 32 位 unsigned 变量,掩码同样是 0x80bit[7] 始终是第 8 位,与数据宽度无关)。

二、分步骤实现:清零、置位、取反

1. 清零操作(将 bit[7] 设为 0,其他位不变)
语法
a &= ~(1 << 7);  
解释
  • 1 << 7:生成掩码 0b10000000bit[7] 为 1,其他位为 0)。
  • ~(1 << 7):对掩码取反,得到 0b01111111bit[7] 为 0,其他位为 1)。
  • a &= ...:按位与操作,bit[7] 与 0 清零,其他位与 1 保留原值。
示例

假设 a = 0b101010100xAA),执行后:

a &= ~(1 << 7);  // 0b10101010 & 0b01111111 = 0b00101010(`bit[7]` 清零,其他位不变)  
2. 置位操作(将 bit[7] 设为 1,其他位不变)
语法
a |= (1 << 7);  
解释
  • 1 << 7:生成掩码 0b10000000bit[7] 为 1,其他位为 0)。
  • a |= ...:按位或操作,bit[7] 与 1 置位,其他位与 0 保留原值。
示例

假设 a = 0b001010100x2A),执行后:

a |= (1 << 7);  // 0b00101010 | 0b10000000 = 0b10101010(`bit[7]` 置位,其他位不变)  
3. 取反操作(将 bit[7] 翻转,0 变 1,1 变 0,其他位不变)
语法
a ^= (1 << 7);  
解释
  • 1 << 7:生成掩码 0b10000000bit[7] 为 1,其他位为 0)。
  • a ^= ...:按位异或操作,bit[7] 与 1 翻转,其他位与 0 保留原值(异或 0 不变,异或 1 翻转)。
示例
  • 若 a = 0b10101010bit[7] 为 1):
    a ^= (1 << 7);  // 0b10101010 ^ 0b10000000 = 0b00101010(`bit[7]` 从 1 变 0)  
    
  • 若 a = 0b00101010bit[7] 为 0):
    a ^= (1 << 7);  // 0b00101010 ^ 0b10000000 = 0b10101010(`bit[7]` 从 0 变 1)  
    

三、关键细节:为什么用 unsigned 型?

1. 避免符号位问题
  • unsigned 型变量没有符号位,bit[7] 始终是数据位(若用 signedbit[7] 可能是符号位,操作会影响正负判断)。
  • 示例:signed char a = -1(补码 0b11111111),对 bit[7] 清零会改变符号,导致结果为 0b01111111(+127),而 unsigned 无此问题。
2. 掩码通用性
  • 无论 unsigned 是 8 位、16 位还是 32 位,1 << 7 始终对应 bit[7](高位补 0 不影响低 8 位操作)。

四、拓展:位操作的常见应用场景

1. 寄存器位操作(嵌入式核心场景)
  • 控制外设寄存器的某一位(如 GPIO 引脚电平、ADC 控制位):
    volatile unsigned int *GPIO_REG = (volatile unsigned int *)0x40000000;  
    *GPIO_REG |= (1 << 7);  // 置位 GPIO_REG 的 bit[7](输出高电平)  
    
2. 标志位处理
  • 在多线程或中断中设置 / 清除标志位(如任务完成标志):
    unsigned int flag = 0;  
    flag |= (1 << 7);  // 设置标志位 7(任务 A 完成)  
    flag &= ~(1 << 7); // 清除标志位 7(任务 A 重置)  
    
3. 数据压缩与解压缩
  • 从字节中提取某一位或某几位(如传感器数据的状态位):
    unsigned char status = 0b10100001;  
    int bit7_value = (status >> 7) & 1;  // 提取 bit[7] 的值(1 或 0)  
    

五、面试题答案总结

操作语句解释
清零 bit[7]a &= ~(1 << 7);用按位与,将 bit[7] 与 0 清零,其他位与 1 保留原值。
置位 bit[7]`a= (1 << 7);`用按位或,将 bit[7] 与 1 置位,其他位与 0 保留原值。
取反 bit[7]a ^= (1 << 7);用按位异或,bit[7] 与 1 翻转(0→1,1→0),其他位与 0 保留原值。

六、实战避坑指南

  1. 掩码优先级

    • 始终用括号包裹 1 << n,避免优先级错误(如 ~1 << 7 实际是 ~(1 << 7),而非 (~1) << 7)。
  2. 数据宽度匹配

    • 若操作 16 位 / 32 位变量,掩码 1 << 7 依然有效(仅操作低 8 位的 bit[7])。
  3. 无符号操作

    • 确保变量为 unsigned 型,避免符号位干扰(如 signed int 的 bit[31] 是符号位,操作会改变数值符号)。

总结

位操作是嵌入式开发的核心技能,尤其在寄存器配置、标志位控制中不可或缺。通过 &|^ 配合掩码 1 << n,可精准操作任意位。理解清零、置位、取反的底层逻辑,能有效提升代码效率和硬件交互的准确性,是嵌入式工程师必备的基础能力。

相关文章:

嵌入式面试题解析:常见基础知识点详解

在嵌入式领域的面试中&#xff0c;基础知识点的考察尤为重要。下面对一些常见面试题进行详细解析&#xff0c;帮助新手一步步理解。 一、原码、反码、补码及补码的好处 题目 什么叫原码、反码、补码&#xff1f;计算机学科引入补码有什么好处&#xff1f; 在计算机科学中&a…...

GPU渲染阶段介绍+Shader基础结构实现

GPU是什么 &#xff08;CPU&#xff09;Center Processing Unit:逻辑编程 &#xff08;GPU&#xff09;Graphics Processing Unit&#xff1a;图形处理&#xff08;矩阵运算&#xff0c;数据公式运算&#xff0c;光栅化&#xff09; 渲染管线 渲染管线也称为渲染流水线&#x…...

08-DevOps-向Harbor上传自定义镜像

harbor创建完成&#xff0c;往harbor镜像仓库中上传自定义的镜像&#xff0c;包括新建项目、docker配置镜像地址、镜像重命名、登录harbor、推送镜像这几个步骤&#xff0c;具体操作如下&#xff1a; harbor中新建项目 访问级别公开&#xff0c;代表任何人都可以拉取仓库中的镜…...

C++学习之路,从0到精通的征途:vector类的模拟实现

目录 一.vector的介绍 二.vector的接口实现 1.成员变量 2.迭代器 &#xff08;1&#xff09;begin &#xff08;2&#xff09;end 3.容量操作 &#xff08;1&#xff09;size&#xff0c;capacity &#xff08;2&#xff09;reserve &#xff08;3&#xff09;resize…...

嵌入式软件--stm32 DAY 2

大家学习嵌入式的时候&#xff0c;多多学习用KEIL写代码&#xff0c;虽然作为编译器&#xff0c;大家常用vscode等常用工具关联编码&#xff0c;但目前keil仍然是主流工具之一&#xff0c;学习掌握十分必要。 1.再次创建项目 1.1编译器自动生成文件 1.2初始文件 这样下次创建新…...

多模态大语言模型arxiv论文略读(二十九)

Temporal Insight Enhancement: Mitigating Temporal Hallucination in Multimodal Large Language Models ➡️ 论文标题&#xff1a;Temporal Insight Enhancement: Mitigating Temporal Hallucination in Multimodal Large Language Models ➡️ 论文作者&#xff1a;Li Su…...

【人工智能学习-01-01】20250419《数字图像处理》复习材料的word合并PDF,添加页码

前情提要 20250419今天是上师大继续教育人工智能专升本第一学期的第一次线下课。 三位老师把视频课的内容提炼重点再面授。&#xff08;我先看了一遍视频&#xff0c;但是算法和图像都看不懂&#xff0c;后来就直接挂分刷满时间&#xff0c;不看了&#xff09; 今天是面对面授…...

B端APP设计:打破传统限制,为企业开启便捷新通道

B端APP设计&#xff1a;打破传统限制&#xff0c;为企业开启便捷新通道 在数字化转型浪潮中&#xff0c;企业级移动应用正突破传统管理系统的功能边界&#xff0c;演变为连接产业链各环节的核心枢纽。本文从技术架构革新、交互模式进化、安全防护升级三个维度&#xff0c;系统…...

【多线程5】面试常考锁知识点

文章目录 悲观/乐观锁挂起等待锁/自旋锁偏向锁轻量级/重量级锁锁升级CASCAS引发的ABA问题解决方案 原子类 公平/不公平锁可重入锁ReentrantLock读写锁 Callable接口 这里的“悲观”“乐观”“挂起等待”“自旋”“轻量级”“重量级”“公平”“非公平”“可重入”仅代表某个锁的…...

Linux第一个系统程序——进度条

1.回车与换行 回车&#xff08;CR, \r&#xff09;&#xff1a; 作用&#xff1a;将光标移动到当前行的行首&#xff08;最左侧&#xff09;&#xff0c;但不换到下一行。 历史来源&#xff1a;源自打字机的“回车”操作——打字机的滑架&#xff08;Carriage&#xff09;需…...

C 语 言 --- 指 针 3

C 语 言 --- 指 针 3 函 数 指 针函 数 指 针 数 组代 码 解 释回 调 函 数 - - - qsort模 拟 实 现 qsort 函 数 总结 &#x1f4bb;作 者 简 介&#xff1a;曾 与 你 一 样 迷 茫&#xff0c;现 以 经 验 助 你 入 门 C 语 言 &#x1f4a1;个 人 主 页&#xff1a;笑口常开x…...

蓝桥杯之递归

1.数字三角形 题目描述 上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径&#xff0c;把路径上面的数加起来可以得到一个和&#xff0c;你的任务就是找到最大的和&#xff08;路径上的每一步只可沿左斜线向下或右斜线向下走&#xff09;。 输…...

学习笔记十八——Rust 封装

&#x1f9f1; Rust 封装终极指南&#xff1a;结构体、模块、Trait、目录结构与模块引用 &#x1f9ed; 目录导航 什么是封装&#xff1f;Rust 的封装理念Rust 的封装工具总览模块&#xff08;mod&#xff09;和访问控制&#xff08;pub&#xff09;详解结构体和枚举&#xff…...

【面试向】点积与注意力机制,逐步编码理解自注意力机制

点积&#xff08;dot product&#xff09;两个向量点积的数学公式点积&#xff08;dot product&#xff09;与 Attention 注意力机制&#xff08;Attention&#xff09;注意力机制的核心思想注意力机制中的缩放点积自注意力机制中&#xff0c;谁注意谁&#xff1f; 逐步编码理解…...

基础数学知识-线性代数

1. 矩阵相乘 c i j = a i k ∗ b k j c_{ij} = a_{ik} * b_{kj} cij​=aik​∗bkj​ 1. 范数 1. 向量的范数 任意一组向量设为 x ⃗ = ( x 1 , x 2 , . . . , x N ) \vec{x}=(x_1,x_2,...,x_N) x =(x1​,x2​,...,xN​) 如下: 向量的1范数: 向量的各个元素的绝对值之和∥ …...

【KWDB 创作者计划】_上位机知识篇---Docker容器

文章目录 前言1. Docker 容器是什么&#xff1f;隔离性轻量级可移植性可复用性 2. Docker 核心概念镜像容器仓库Dockerfile 3. Docker 基本使用(1) 安装 Docker(2) 容器生命周期管理(3) 镜像管理(4) 进入容器内部(5) 数据持久化&#xff08;挂载卷&#xff09;(6) 网络管理 4. …...

指针函数和函数指针

指针函数本质是一个函数&#xff0c;只是函数的返回值是指针类型 函数指针本质是一个指针&#xff0c;只是这个指针指向的是一个函数 指针函数 函数有很多类型的返回值&#xff0c;例如 short funcA(参数列表) // 表示该函数返回值是一个short类型 void funcA(参数列表) // 表…...

案例驱动的 IT 团队管理:创新与突破之路:第六章 组织进化:从案例沉淀到管理体系-6.1 案例库建设方法论-6.1.2案例分级与标签体系

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 文章大纲 案例分级与标签体系构建方法论&#xff1a;IT团队知识管理的结构化实践1. 案例库建设的战略价值与核心挑战1.1 案例管理的战略定位1.2 分级标签体系的核心价值 2. 案例分级体…...

sqlilabs-Less之HTTP头部参数的注入——基础篇

Less-18 user-agent报错注入 这一关的代码漏洞点出现在了insert语句&#xff0c;因为这里没有对user-agent和ip_address进行过滤&#xff0c;&#xff0c;并且输出了mysql的错误信息 补充知识点 PHP里用来获取客户端IP的变量 $_SERVER[HTTP_CLIENT_IP] #这个很少使用&#xf…...

java多线程相关内容

java线程创建的方式 一共有四种方式 继承 Thread 类&#xff1a;本质上是实现了 Runnable 接口的一个实例&#xff0c;代表一个线程的实例 启动线程的唯一方 法就是通过 **Thread 类的 start()**实例方法。start()方法是一个 native 方法&#xff0c;它将启动一个新线 程&…...

Windows Server .NET Core 应用程序部署到 IIS 解决首次访问加载慢的问题

第一篇&#xff1a; Windows .NET Core 应用程序部署到 IIS 解决首次访问加载慢的问题 第二篇&#xff1a;Windows Server .NET Core 应用程序部署到 IIS 解决首次访问加载慢的问题 第三篇&#xff1a;Windows .NET Core 应用程序部署到 IIS 解决首次访问加载慢的问题 设置…...

ubuntu24.04上使用qemu+buildroot+uboot+linux+tftp+nfs模拟搭建vexpress-ca9嵌入式linux开发环境

1 准备工作 1.1 安装依赖工具 sudo apt-get update && sudo apt-get install build-essential git bc flex libncurses5-dev libssl-dev device-tree-compiler1.2 安装arm交叉编译工具链 sudo apt install gcc-arm-linux-gnueabihf安装之后&#xff0c;在终端输入ar…...

Cocos Creater打包安卓App添加隐私弹窗详细步骤+常见问题处理

最终演示效果,包含所有代码内容 + 常见错误问题处理 点击服务协议、隐私政策,跳转到相关网页, 点击同意进入游戏,不同意关闭应用 一,添加Activity,命名为MyLaunchActivity 二,编写MyLaunchActivity.java的内容 package com.cocos.game.launch;import android.os.Bund…...

UI文件上传

1、文件上传&#xff1a;文件上传是自动化中比较麻烦棘手的部分。 有些场景我们需要上传本地文件到项目里。这种比较麻烦&#xff0c;因为需要点开文件上传的窗口后&#xff0c;打开的是windows的文件选择窗口&#xff0c; 而selenium是无法操作这个窗口的。 selenium只能操作…...

2.凸包优化求解

1.减而治之(Decrease and Conquer) 插入排序 典型的减而治之算法就是插入排序方法 插入排序法: 在未排序中选择一个元素&#xff0c;插入到已经排序号的序列中 将凸包也采用减而治之的方法 2.In-Convex-Polygon Test 怎么判断引入的极点存在于多边形里面还是外面&#xff1…...

从0开发一个unibest+vue3项目,使用vscode编辑器开发,总结vue2升vue3项目开始,小白前期遇到的问题

开头运行可看官网 链接: unibest官网 一&#xff1a;vscode中vue3代码显示报错标红波浪线 去查看扩展商店发现一些插件都弃用了&#xff0c;例如h5的插件以及vue老插件 解决办法&#xff1a;下载Vue - Official插件&#xff08;注意&#xff1a;横杠两边是要加空格的&#xff…...

jmeter中文乱码问题解决

修改jmeter.properties配置文件‌ 进入JMeter安装目录的bin文件夹&#xff0c;找到jmeter.properties文件。搜索参数sampleresult.default.encodingUTF-8&#xff0c;取消注释&#xff08;删除行首的#&#xff09;&#xff0c;并将其值改为UTF-8。保存文件并‌重启JMeter‌生效…...

额外篇 非递归之美:归并排序与快速排序的创新实现

个人主页&#xff1a;strive-debug 快速排序非递归版本 非递归版本的快速排序是为了解决在空间不够的情况下&#xff0c;利用栈来模拟递归的过程。 递归版本的快速排序是空间换时间&#xff0c;好实现。 实现思路&#xff1a; 1. 创建一个栈&#xff0c;将数组的右边界下标和…...

[文献阅读] EnCodec - High Fidelity Neural Audio Compression

[文献信息]&#xff1a;[2210.13438] High Fidelity Neural Audio Compression facebook团队提出的一个用于高质量音频高效压缩的模型&#xff0c;称为EnCodec。Encodec是VALL-E的重要前置工作&#xff0c;正是Encodec的压缩量化使得VALL-E能够出现&#xff0c;把语音领域带向大…...

JavaSpring 中使用 Redis

创建项目 配置 Redis 服务地址 创建 Controller 类 由于当前只是些简单的测试代码&#xff0c;所以就不进行分层了&#xff0c;只创建一个 Controller 来实现 jedis 通过 jedis 对象里的各种方法来操作 Redis 此处通过 StringRedisTemplate 来操作 Redis 最原始提供的类是 Re…...

B端可视化像企业数据的透视镜,看清关键信息

在数字化时代&#xff0c;数据已成为企业最宝贵的资产之一。然而&#xff0c;数据的价值不仅取决于其数量&#xff0c;更在于企业能否快速、准确地提取关键信息并据此做出决策。B端可视化技术的出现&#xff0c;为企业提供了一种强大的工具&#xff0c;它如同企业的“透视镜”&…...

【愚公系列】《Python网络爬虫从入门到精通》055-Scrapy_Redis分布式爬虫(安装Redis数据库)

&#x1f31f;【技术大咖愚公搬代码&#xff1a;全栈专家的成长之路&#xff0c;你关注的宝藏博主在这里&#xff01;】&#x1f31f; &#x1f4e3;开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主&#xff01; &#x1f…...

【MySQL】SQL语句在MySQL中的执行过程?主要存储引擎区别?

MySQL SQL语句执行过程详解 作为面试官&#xff0c;我来详细剖析一条SQL语句在MySQL中的完整执行过程&#xff0c;这是每个后端开发者都应该掌握的核心知识。 一、连接阶段 建立连接 客户端通过TCP/IP协议与MySQL服务器建立连接(默认3306端口)服务器验证用户名、密码和权限…...

致远OA——数据回填表单

文章目录 :apple: 业务需求描述:pineapple: 业务分析和实现 &#x1f34e; 业务需求描述 测试案例&#xff1a; https://pan.quark.cn/s/3f58972f0a27 官网地址&#xff1a; https://open.seeyoncloud.com/v5devCAP/94/355/359/399/405/406.html 需求描述&#xff1a; 点…...

MongoDB导出和导入数据

安装mongodump工具 参考文章mongodump工具安装及使用详解_mongodump安装-CSDN博客 MongoDB导入导出和备份的命令工具从4.4版本开始不再自动跟随数据库一起安装&#xff0c;而是需要自己手动安装。 官方网站下载链接&#xff1a;Download MongoDB Command Line Database Tools …...

蓝桥杯之递归二

1.数的划分 题目描述 将整数 nn 分成 kk 份&#xff0c;且每份不能为空&#xff0c;任意两份不能相同(不考虑顺序)。 例如&#xff1a;n7&#xff0c;k3n7&#xff0c;k3&#xff0c;下面三种分法被认为是相同的。 1&#xff0c;1&#xff0c;5;1&#xff0c;5&#xff0c;…...

【大疆dji】ESDK开发环境搭建(软件准备篇)

接上一篇【大疆dji】ESDK开发环境搭建&#xff08;硬件准备篇&#xff09; 1. 编译环境 ESDK 提供 x86_64/aarch64 基于 Linux 平台 Ubuntu 发行版操作系统构建的静态库&#xff0c;运行 demo 先正确安装所需的依赖包。arm32位就不支持了。建议使用编译安装的方式&#xff0c;…...

Android TTY设备调用流程和简单分析

Linux TTY系统中ioctl的调用流程详解:从应用层到MSM GENI Serial驱动 本文档详细分析Linux系统中从用户空间应用程序发起TTY ioctl请求到特定驱动(例如msm_geni_serial_ioctl)的完整调用流程,包括32位应用与64位内核之间的兼容性问题分析。 1. 总体调用路径概览 以下是完…...

数字孪生赋能管理系统,降本增效立竿见影

1. 数字孪生基础概念及其在管理系统中的应用前景 数字孪生是一种集成多学科、多物理量、多尺度、多概率的仿真过程&#xff0c;在虚拟空间中完成映射&#xff0c;从而反映相对应的实体装备的全生命周期过程。其核心在于将现实世界中的物理对象或系统与其数字化模型相结合&…...

Java学习手册:Web 应用架构概述

一、Web 应用架构的演变 在互联网发展的初期阶段&#xff0c;Web 应用普遍采用客户端 / 服务器&#xff08;C/S&#xff09;架构模式。客户端应用程序与服务器端应用程序直接建立连接&#xff0c;进行数据交互和业务处理。然而&#xff0c;这种架构存在诸多局限性。由于客户端…...

企业网站安装 SSL安装的必要性

能够带来安全的加密和快速的访问体验&#xff0c;防止中间人的流量劫持&#xff0c;保障用户隐私信息的安全&#xff0c;帮助用户识别钓鱼网站&#xff0c;提升网站在搜索引擎的排名。 能够防止黑客盗走客户银行卡账号的机密信息&#xff0c;保证信息的机密性&#xff0c;防止…...

【CF】Day38——Codeforces Round 965 (Div. 2) B

B. Minimize Equal Sum Subarrays 题目&#xff1a; 思路&#xff1a; 直觉题 我们可以这样构造&#xff0c;将整个数列左移一位即可&#xff0c;为什么呢&#xff1f; 因为这样我们能尽可能地保证数列的数字尽可能多的同时 且 有一个数不同 这里介绍一个rorate函数&#xf…...

leetcode 300. Longest Increasing Subsequence

目录 题目描述 第一步&#xff0c;明确并理解dp数组及下标的含义 第二步&#xff0c;分析明确并理解递推公式 第三步&#xff0c;理解dp数组如何初始化 第四步&#xff0c;理解遍历顺序 代码 题目描述 这是动态规划解决子序列问题的例子。 第一步&#xff0c;明确并理解…...

解密大模型背后的秘密:训练、优化与挑战

解密大模型背后的秘密&#xff1a;训练、优化与挑战 在当今的人工智能领域&#xff0c;大模型&#xff08;Large Language Models, LLMs&#xff09;已经成为了一个不可忽视的存在。从自然语言处理到图像生成&#xff0c;再到推荐系统&#xff0c;大模型以其强大的泛化能力和创…...

第33讲|遥感大模型在地学分类中的初探与实战

目录 🧠 一、什么是“遥感大模型”? 📚 二、遥感大模型在地学分类中的优势 📍三、案例:使用 Segment Anything Model (SAM) 进行遥感地物分割 📦 1. 安装与依赖配置(PyTorch) 🖼 2. 读取遥感图像(可用 Sentinel-2 伪彩色图) 🔧 3. SAM 模型载入 💡 …...

LeetCode 438 找到字符串中所有字母异位词

给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 示例 1: 输入: s "cbaebabacd", p "abc" 输出: [0,6] 解释: 起始索引等于 0 的子串是 "cba", 它是 "…...

【25软考网工笔记】第二章(6)脉冲编码调制PCM、通信和交换方式

目录 一、脉冲编码调制PCM 1. 脉冲编码调制的数字化过程 1&#xff09;采样 2&#xff09;量化 3&#xff09;编码 2. PCM计算 3. 应用案例 1&#xff09;例题1 2&#xff09;例题1 3&#xff09;例题3 知识小结 二、通信和交换方式 1.数据通信方式分类 1&#x…...

JSON学习笔记

文章目录 1. JSON是什么2. JSON的特点与结构3. JSON的使用4. JSON文件读取 1. JSON是什么 JSON&#xff08;JavaScript Object Notation&#xff0c;JavaScript对象表示法&#xff09;是一种轻量级的数据交换格式&#xff0c;易于人阅读和编写&#xff0c;同时也易于机器解析和…...

高阶指南:动态定价下eBay利润率控制的4维财务模型

在eBay平台上&#xff0c;动态定价&#xff08;Dynamic Pricing&#xff09;早已不是新鲜概念。随着市场供需的瞬时波动、竞争产品的变化&#xff0c;以及跨境电商红海局势的加剧&#xff0c;卖家若想在残酷的价格战中保住利润、稳住运营基本盘&#xff0c;仅靠经验主义已经远远…...

【NLP 66、实践 ⑰ 基于Agent + Prompt Engineering文章阅读】

你用什么擦干我的眼泪 莎士比亚全集 工业纸巾 还是你同样泛红的眼睛 —— 4.19 一、⭐【核心函数】定义大模型调用函数 call_large_model prompt&#xff1a;用户传入的提示词&#xff08;如 “请分析这篇作文的主题”&#xff09;&#xff0c;指导模型执行任务 client&…...