嵌入式笔试刷题专栏(第三天)

1. 试写一个函数检查表达式中的括号是否匹配。

检查的括号包括:()[]{}<>

例如:表达式中前面有 但后面没有 ,则认为不匹配。

✅ 答案:

#include <stdbool.h>

#define MAX_STACK 100

bool is_match(char* s) {
    char stack[MAX_STACK];
    int top = -1;

    while (*s) {
        if (*s == '(' || *s == '[' || *s == '{' || *s == '<') {
            stack[++top] = *s;
        } else if (*s == ')' || *s == ']' || *s == '}' || *s == '>') {
            if (top < 0) return false;
            char left = stack[top--];
            if ((*s == ')' && left != '(') ||
                (*s == ']' && left != '[') ||
                (*s == '}' && left != '{') ||
                (*s == '>' && left != '<')) {
                return false;
            }
        }
        s++;
    }
    return top == -1;
}

2. 编写函数,根据公式计算表达式:

s = 1 + 1/(1+2) + 1/(1+2+3) + ... + 1/(1+2+3+...+n)

n 作为参数传入。

例如:n = 11 时,s = 1.833333

✅ 答案:

double calc_s(int n) {
    double s = 0.0;
    int sum = 0;
    for (int i = 1; i <= n; i++) {
        sum += i;
        s += 1.0 / sum;
    }
    return s;
}

3. 写一个宏定义:输入两个参数,返回较小的一个。

✅ 答案:

#define MIN(a, b) ((a) < (b) ? (a) : (b))

4. 分析下面这段代码的输出,并说明原因:

union {
    int i;
    struct {
        char first;
        char second;
    } half;
} number;

number.i = 0x4241;
printf("%x%x\n", number.half.first, number.half.second);
number.half.first = 97;
number.half.second = 98;
printf("%x\n", number.i);

✅ 答案:

假设是 小端字节序(常见于 x86 平台):

  • number.i = 0x4241,低位字节为 0x41,高位为 0x42
  • 所以 first = 0x41second = 0x42,输出为:
  • 修改 first = 97(0x61)、second = 98(0x62) 合并为低位 0x61、高位 0x62 ⇒ 输出为:

5. 写出单精度浮点数 -12.75 在内存中的十六进制表示

✅ 答案:

IEEE 754 单精度格式:

  • -12.75 = -1100.11₂ = -1.10011 × 2³
  • 符号位:1
  • 阶码:3 + 127 = 130 = 10000010
  • 尾数(去掉最高的1):10011000000000000000000

二进制组合:

1 10000010 10011000000000000000000

换算为十六进制:

C1500000

6. 指出下面程序的错误

void prinf_base16(unsigned long num) {
    char *buf;
    unsigned long temp;
    int i = 0;

    while(num > 0) {
        temp = num % 16;
        num /= 16;
        if(temp > 9)
            buf[i++] = temp - 9 + 'A';
        else
            buf[i++] = temp;
    }

    while(i) {
        putchar(buf[i]);
        i--;
    }
}

✅ 错误分析:

  1. buf 未分配内存,使用未初始化指针,会段错误;
  2. temp 是整数,但没有加 '0' 转换为字符;
  3. buf[i] 输出应为 buf[--i] 否则数组越界。

✅ 正确写法:

void prinf_base16(unsigned long num) {
    char buf[32];
    unsigned long temp;
    int i = 0;

    while(num > 0) {
        temp = num % 16;
        num /= 16;
        if(temp > 9)
            buf[i++] = temp - 10 + 'A';
        else
            buf[i++] = temp + '0';
    }

    while(i) {
        putchar(buf[--i]);
    }
}

7. 网络编程中并发服务器:多进程 vs 多线程 有什么区别?

✅ 答案:

内存空间

各进程独立

线程共享内存

创建/销毁开销

较大(

fork()

较小(

pthread_create

数据共享

需使用 IPC 机制

可直接共享全局变量

稳定性

单个子进程崩溃不影响其他

一个线程崩溃可能影响整个进程

编程难度

程序结构清晰、调试简单

编程复杂,注意线程安全

使用场景

Apache(多进程)

Nginx、游戏服务器(多线程)

8. 解释 IP 协议的定义及其作用,位于哪个层?TCP 和 UDP 呢?

✅ 答案:

  • IP 协议所在层级:网络层作用:提供主机寻址与路由功能,标识设备之间的通信路径使用逻辑地址(IP 地址)
  • TCP 协议所在层级:传输层特点:面向连接、可靠传输(顺序、重传、拥塞控制)应用场景:HTTP、FTP、SSH
  • UDP 协议所在层级:传输层特点:无连接、不保证可靠传输,速度快应用场景:音视频、DNS、游戏

9. #include <file.h>#include "file.h" 的区别?

✅ 答案:

  • #include <file.h>:编译器从系统目录(如 /usr/include)查找头文件。
  • #include "file.h":编译器先在当前目录查找,找不到再去系统目录查找。

10. 用预处理指令 #define 声明一个常数,用以表示 1 年中有多少秒(忽略闰年)

✅ 答案:

#define SECONDS_PER_YEAR (365 * 24 * 60 * 60)  // 31536000

嵌入式笔试专栏 文章被收录于专栏

本专栏系统整理了嵌入式方向笔试中常见的知识点和高频考题,涵盖基础理论、常用算法、C语言陷阱、操作系统原理、驱动开发、常见外设通信协议(如 I2C/SPI/UART)、RTOS、Linux 内核、以及实用电路知识等内容。

全部评论

相关推荐

非堵塞&nbsp;IO、事件循环(Event&nbsp;Loop)和事件队列是现代&nbsp;JavaScript&nbsp;和&nbsp;Node.js&nbsp;应用程序中用于处理异步操作的核心概念。它们共同工作,使得在单线程环境下能够高效地处理输入/输出操作。以下是这些概念的详细解释:https://www.nowcoder.com/issue/tutorial?zhuanlanId=j572L2&amp;amp;uuid=19017e996e2444a8b05bf61a3285892f1.&nbsp;非堵塞&nbsp;IO非堵塞&nbsp;IO(Non-blocking&nbsp;IO)是一种输入输出操作的方式,它不会阻塞程序的执行。传统的阻塞&nbsp;IO&nbsp;会使得程序在等待一个操作完成时暂停执行,这可能导致效率低下。非堵塞&nbsp;IO&nbsp;则允许程序继续执行其他任务,直到数据准备好或者操作完成。在&nbsp;Node.js&nbsp;中,很多&nbsp;IO&nbsp;操作(如文件读取、数据库查询和网络请求等)都是非堵塞的。这意味着,发起一个&nbsp;IO&nbsp;操作后,Node.js&nbsp;不会等到操作完成才继续执行后面的代码,而是立即返回,待操作完成时,通过回调函数、Promises&nbsp;或&nbsp;async/await&nbsp;来处理结果。2.&nbsp;事件循环(Event&nbsp;Loop)事件循环(Event&nbsp;Loop)是&nbsp;JavaScript&nbsp;的一种机制,负责管理异步操作的运行。由于&nbsp;JavaScript&nbsp;是单线程的,事件循环的主要目的是协调执行栈(call&nbsp;stack)和事件队列(event&nbsp;queue),处理异步操作。事件循环的工作流程如下:执行栈(Call&nbsp;Stack):所有的&nbsp;JavaScript&nbsp;代码都是在执行栈中执行的。当前执行的任务会被压入栈中,完成后从栈中弹出。事件队列(Event&nbsp;Queue):当异步操作完成(如网络请求、定时器等),相应的回调函数会被放入事件队列中,等待执行栈闲暇时进行处理。事件循环的运行:事件循环会不断检查执行栈是否为空。如果栈为空,它会从事件队列中取出第一个事件,并将其执行(即执行对应的回调函数)。如果执行栈不为空,它会继续执行栈中的任务,直到栈清空。这个机制保证了&nbsp;JavaScript&nbsp;在处理异步任务时的高效性,不会因为等待&nbsp;IO&nbsp;操作而阻塞整个程序的执行。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务