嵌入式八股文面试题(二)C语言算法

news2025/2/14 2:32:23

相关概念请查看文章:C语言概念。

1. 如何实现一个简单的内存池?

简单实现:

#include <stdio.h>
#include <stdlib.h>

//内存块
typedef struct MemoryBlock {
    void *data; // 内存块起始地址
    struct MemoryBlock *next; // 下一个内存块的地址
} MemoryBlock;

//内存池
typedef struct MemoryPool {
    MemoryBlock *freeList; // 空闲内存块链表
    MemoryBlock *usedList; // 占用内存块链表
    int freeCount; // 空闲内存块数量
    int usedCount; // 占用内存块数量
    int blockCount; // 内存块总数量
} MemoryPool;
//初始化内存池
MemoryPool *InitMemoryPool(int blockSize, int blockCount) {
    MemoryPool *pool = (MemoryPool *)malloc(sizeof(MemoryPool)); // 为内存池分配空间
    if (pool == NULL) {
        printf("Failed to allocate memory pool!\n");
        return NULL;
    }
    pool->freeList = NULL;
    pool->usedList = NULL;
    pool->freeCount = 0;
    pool->usedCount = 0;
    pool->blockCount = blockCount;
    for (int i = 0; i < blockCount; i++) {
        // 创建内存块节点,插入到空闲链表
        MemoryBlock *block = (MemoryBlock *)malloc(sizeof(MemoryBlock));
        block->data = malloc(blockSize);
        block->next = pool->freeList;
        pool->freeList = block;
        pool->freeCount++;
    }
    return pool;
}
//分配内存块
void *AllocateBlock(MemoryPool *pool) {
    if (pool->freeList == NULL || pool->freeCount == 0) {
        printf("No free blocks available!\n");
        return NULL;
    }
    MemoryBlock *node = pool->freeList;
    // 将该内存块从空闲链表删除
    pool->freeList = node->next;
    // 将该内存块插入到占用链表
    node->next = pool->usedList;
    pool->usedList = node;
    // 更新空闲和占用状态
    pool->usedCount++;
    pool->freeCount--;
    return node->data;
}
//释放内存块
void FreeBlock(MemoryPool *pool, void *data) {
    MemoryBlock *cur = pool->usedList;
    MemoryBlock *pre = NULL;
    // 寻找该内存块的节点
    while (cur != NULL && cur->data != data) {
        pre = cur;
        cur = cur->next;
    }
    if (cur == NULL) {
        printf("Error: Data not found!\n");
        return;
    }
    // 将该内存块从占用链表删除
    if (pre != NULL)
        pre->next = cur->next;
    else
        pool->usedList = cur->next;
    // 将该内存块插入到空闲链表
    cur->next = pool->freeList;
    pool->freeList = cur;
    pool->freeCount++;
    pool->usedCount--;
}
//销毁内存块
void DestroyMemoryPool(MemoryPool *pool) {
    if (pool == NULL) return;
    MemoryBlock *cur = NULL;
    // 释放所有空闲内存块空间
    while (pool->freeList != NULL) {
        cur = pool->freeList;
        pool->freeList = pool->freeList->next;
        free(cur->data);
        free(cur);
    }
    // 释放所有占用内存块空间
    while (pool->usedList != NULL) {
        cur = pool->usedList;
        pool->usedList = pool->usedList->next;
        free(cur->data);
        free(cur);
    }
    // 释放内存池空间
    free(pool);
}
int main(void) {
    MemoryPool *pool;
    pool = InitMemoryPool(10, 5); // 初始化内存池
    int *str = (int *)AllocateBlock(pool);  //申请内存块1
    *str = 2;
    int *ptr = (int *)AllocateBlock(pool); //申请内存块2
    *ptr = 3;
    printf("free block : %d, used block : %d\n", pool->freeCount, pool->usedCount);
    FreeBlock(pool, ptr); //释放内存块2
    printf("free block : %d, used block : %d\n", pool->freeCount, pool->usedCount);
    DestroyMemoryPool(pool); 
    return 0;
}

打印结果: 

2. 实现一个双向链表。

        双向链表是一种每个节点都有两个指针,一个指向下一个节点,一个指向前一个节点的数据结构。可以在任意位置进行快速插入和删除。

#include <stdio.h>
#include <stdlib.h>

// 双向链表节点
typedef struct Node {
    int data;
    struct Node *prev; //连接前一个节点的指针
    struct Node *next; //连接下一个节点的指针
} Node;

// 创建新节点
Node* createNode(int data) {
    Node *newNode = (Node *)malloc(sizeof(Node));
    newNode->data = data;
    newNode->next = NULL;
    newNode->prev = NULL;
    return newNode;
}

// 插入节点到链表的尾部
void append(Node **head, int data) {
    Node *newNode = createNode(data);
    if (*head == NULL) {
        *head = newNode;
    } else {
        Node *temp = *head;
        while (temp->next != NULL) {
            temp = temp->next;
        }
        temp->next = newNode;
        newNode->prev = temp;
    }
}
//删除一个节点
void delete_node(Node **head, int data) {
    if (*head == NULL){  // 如果链表为空
        printf("链表为空,没有要删除的元素\n");
        return;
    }
    Node *temp = *head;
    
    // 如果删除的是头节点
    if (temp->data == data) {
        *head = temp->next;  // 更新头节点
        if (*head != NULL) {  // 如果不是空链表
            (*head)->prev = NULL;
        }
        free(temp);
        return;
    }
    // 找到要删除的节点
    while (temp != NULL && temp->data != data) {
        temp = temp->next;
    }
    // 如果没有找到该节点
    if (temp == NULL) {
        printf("未找到数据为 %d 的节点\n", data);
        return;
    }
    // 删除的是中间或尾部节点
    if (temp->next != NULL) {
        temp->next->prev = temp->prev;  // 更新下一个节点的prev指针
    }
    if (temp->prev != NULL) {
        temp->prev->next = temp->next;  // 更新前一个节点的next指针
    }
    free(temp);
}
// 打印双向链表
void printList(Node *head) {
    Node *temp = head;
    while (temp != NULL) {
        printf("%d <-> ", temp->data);
        temp = temp->next;
    }
    printf("NULL\n");
}

int main() {
    Node *head = NULL;
    append(&head, 10);
    append(&head, 20);
    append(&head, 30);
    printList(head);
    delete_node(&head, 30);
    printList(head);
    return 0;
}

打印结果:

3. 实现一个线程池。

   

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2297663.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

#渗透测试#批量漏洞挖掘#LiveBos UploadFile 任意文件上传漏洞

免责声明 本教程仅为合法的教学目的而准备,严禁用于任何形式的违法犯罪活动及其他商业行为,在使用本教程前,您应确保该行为符合当地的法律法规,继续阅读即表示您需自行承担所有操作的后果,如有异议,请立即停止本文章读。 目录 漏洞背景 漏洞成因 影响评估 检测方案 …

ds-download-link 插件:以独特图标选择,打造文章下载链接

源码介绍 “ds-download-link”插件为 WordPress 网站提供了在文章编辑器中添加下载链接的功能&#xff0c;每个下载链接都支持图标选择&#xff0c;并能将这些链接以美观的样式展示在文章前端页面。以下是该插件的主要特性和功能&#xff1a; 后台功能 在文章编辑器下方添加…

判断函数是否为react组件或lazy包裹的组件

function Modal(){return <p>123</p> } 实参里填入函数名,是false 实参里填入标签形式的函数,是true isValidElement(Modal)//false isValidElement(<Modal></Modal>)//true 官方说明 isValidElement – React 中文文档 但是官方并不建议用isValidE…

PHP 中的除以零错误

除以零错误&#xff08;Division by zero&#xff09;是指数字除以零的情况&#xff0c; 这在数学上是未定义的。在 PHP 中&#xff0c;处理这种错误的方式取决于 PHP 版本&#xff1a; PHP 7&#xff1a; 使用 / 运算符会产生一个警告 (E_WARNING) 并返回 false。 使用 intd…

【QT】控件 -- 多元素类 | 容器类 | 布局类

&#x1f525; 目录 一、多元素类1. List Widget -- 列表2. Table Widget -- 表格3. Tree Widget -- 树形 二、容器类1. Group Box -- 分组框2. Tab Widget -- 标签页 三、布局类1. 垂直布局【使用 QVBoxLayout 管理多个控件】【创建两个 QVBoxLayout】 2. 水平布局【使用 QHBo…

NO.15十六届蓝桥杯备战|while循环|六道练习(C++)

while循环 while语法形式 while 语句的语法结构和 if 语句⾮常相似&#xff0c;但不同的是 while 是⽤来实现循环的&#xff0c; if 是⽆法实现循环的。 下⾯是 while 循环的语法形式&#xff1a; //形式1 while ( 表达式 )语句; //形式2 //如果循环体想包含更多的语句&a…

kotlin标准库里面也有很多java类

Kotlin 标准库中确实存在许多与 Java 类直接关联或基于 Java 类封装的结构&#xff0c;但这并不是“问题”&#xff0c;而是 Kotlin 与 JVM 生态深度兼容和互操作性的体现。以下从技术原理和设计哲学的角度详细解释&#xff1a; 一、Kotlin 与 JVM 的底层关系 Kotlin 代码最终…

Flutter 双屏双引擎通信插件加入 GitCode:解锁双屏开发新潜能

在双屏设备应用场景日益丰富的当下&#xff0c;移动应用开发领域迎来了新的机遇与挑战。如何高效利用双屏设备优势&#xff0c;为用户打造更优质的交互体验&#xff0c;成为开发者们关注的焦点。近日&#xff0c;一款名为 Flutter 双屏双引擎通信插件的创新项目正式入驻 GitCod…

01、单片机上电后没有正常运行怎么办

单片机上电后没有运转, 首先要检查什么? 1、单片机供电是否正常? &电路焊接检查 如果连最基本的供电都没有,其它都是空谈啊!检查电路断路了没有?短路了没有?电源合适吗?有没有虚焊? 拿起万用表之前,预想一下测量哪里?供电电压应该是多少?对PCB上电压测量点要…

使用 EMQX 接入 LwM2M 协议设备

LwM2M 协议介绍 LwM2M 是一种轻量级的物联网设备管理协议&#xff0c;由 OMA&#xff08;Open Mobile Alliance&#xff09;组织制定。它基于 CoAP &#xff08;Constrained Application Protocol&#xff09;协议&#xff0c;专门针对资源受限的物联网设备设计&#xff0c;例…

使用 mkcert 本地部署启动了 TLS/SSL 加密通讯的 MongoDB 副本集和分片集群

MongoDB 是支持客户端与 MongoDB 服务器之间启用 TLS/SSL 进行加密通讯的, 对于 MongoDB 副本集和分片集群内部的通讯, 也可以开启 TLS/SSL 认证. 本文会使用 mkcert 创建 TLS/SSL 证书, 基于创建的证书, 介绍 MongoDB 副本集、分片集群中启动 TLS/SSL 通讯的方法. 我们将会在…

P3372 【模板】线段树 1【题解2】

本题题解分两篇 此篇为第贰篇&#xff0c;用树状数组做 第壹篇&#xff1a;P3372 【模板】线段树 1【题解1】 本文讲解树状数组解决区间修改区间查询 其它树状数组相关文章&#xff1a; 树状数组讲解单点修改/查询树状数组解决区间修改单点查询 P3372 【模板】线段树 1 题…

使用 EDOT 监测由 OpenAI 提供支持的 Python、Node.js 和 Java 应用程序

作者&#xff1a;来自 Elastic Adrian Cole Elastic 很自豪地在我们的 Python、Node.js 和 Java EDOT SDK 中引入了 OpenAI 支持。它们为使用 OpenAI 兼容服务的应用程序添加日志、指标和跟踪&#xff0c;而无需任何代码更改。 介绍 去年&#xff0c;我们宣布了 OpenTelemetry…

CNN-BiGRU卷积神经网络双向门控循环单元多变量多步预测,光伏功率预测

CNN-BiGRU卷积神经网络双向门控循环单元多变量多步预测&#xff0c;光伏功率预测 代码下载&#xff1a;CNN-BiGRU卷积神经网络双向门控循环单元多变量多步预测&#xff0c;光伏功率预测 一、引言 1.1、研究背景及意义 随着全球能源危机和环境问题的日益严重&#xff0c;可再…

mysql8.0使用MGR实现高可用与利用MySQL Router构建读写分离MGR集群

MGR是MySQL Group Replication的缩写&#xff0c;即MySQL组复制。 在以往&#xff0c;我们一般是利用MySQL的主从复制或半同步复制来提供高可用解决方案&#xff0c;但这存在以下几个比较严重的问题&#xff1a; 主从复制间容易发生复制延迟&#xff0c;尤其是在5.6以前的版本…

保研考研机试攻略:python笔记(4)

🐨🐨🐨15各类查找 🐼🐼二分法 在我们写程序之前,我们要定义好边界,主要是考虑区间边界的闭开问题。 🐶1、左闭右闭 # 左闭右闭 def search(li, target): h = len(li) - 1l = 0#因为都是闭区间,h和l都可以取到并且相等while h >= l:mid = l + (h - l) // 2…

关于conda换镜像源,pip换源

目录 1. 查看当前下载源2. 添加镜像源2.1清华大学开源软件镜像站2.2上海交通大学开源镜像站2.3中国科学技术大学 3.删除镜像源4.删除所有镜像源&#xff0c;恢复默认5.什么是conda-forge6.pip换源 1. 查看当前下载源 conda config --show channels 如果发现多个 可以只保留1个…

分布式服务框架 如何设计一个更合理的协议

1、概述 前面我们聊了如何设计一款分布式服务框架的问题&#xff0c;并且编码实现了一个简单的分布式服务框架 cheese, 目前 cheese 基本具备分布式服务框架的基本功能。后面我们又引入了缓存机制&#xff0c;以及使用Socket替代了最开始的 RestTemplate。并且还学习了网络相关…

前端快速生成接口方法

大家好&#xff0c;我是苏麟&#xff0c;今天聊一下OpenApi。 官网 &#xff1a; umijs/openapi - npm 安装命令 npm i --save-dev umijs/openapi 在根目录&#xff08;项目目录下&#xff09;创建文件 openapi.config.js import { generateService } from umijs/openapi// 自…

mysql 学习12 存储引擎,mysql体系结构

mysql 体系结构 存储引擎简介 存储引擎 就是 存储数据&#xff0c;建立索引&#xff0c;更新/查询 数据等技术的实现方式。 存储引擎 是基于表的&#xff0c;而不是基于库的&#xff0c;所以存储引擎也可以称为 表类型 mysql默认的使用InnoDB 做为存储引擎 查看一下我们之前…