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

C/C++ 面试复习笔记(2)

C语言如何实现快速排序算法?

  • 答案:快排是一种分治算法,选择一个基准元素,将数据划分成两部分,然后递归排序

  • 补充:

void quick_sort(int arr[], int start, int end)
{//判断是否需要排序if (start >= end){return;}
​int left = start;int right = end;int pivot = arr[left];  //基准值while (left < right){//实现大于基准值的数字放到左边while ((arr[right] > pivot) && (left < right)){right--;}if (left < right){arr[left] = arr[right]; //将基准值填入left++;}//实现小于基准值的数字放到右while ((arr[left] < pivot) && (left < right)){left++;}if (left < right){arr[right] = arr[left]; //将基准值填入right--;}arr[left] = pivot;}//递归排序quick_sort(arr, start, left - 1);quick_sort(arr, right+1, end);
}

C语言中的setvbuf函数作用是什么?

  • 答案:setvbuf 用于设置文件流的缓冲区模式和大小,优化文件读写的性能。

  • 解析:setvbuf 可以设置缓冲区类型(如全缓冲、无缓冲、行缓冲),并定义缓冲区的大小, 适用于文件流的优化。

  • 补充:

缓冲区的类型

缓冲区分为三种类型:全缓冲、行缓冲和不缓冲。

1、全缓冲

在这种情况下,当填满标准I/O缓存后才进行实际I/O操作。全缓冲的典型代表是对磁盘文件的读写。

2、行缓冲

在这种情况下,当在输入和输出中遇到换行符时,执行真正的I/O操作。这时,我们输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O操作。典型代表是键盘输入数据。

3、不缓冲

也就是不进行缓冲,标准出错情况stderr是典型代表,这使得出错信息可以直接尽快地显示出来。

缓冲区的刷新

下列情况会引发缓冲区的刷新:

  1. 缓冲区满时;

  2. 执行fflush函数;

  3. 正常关闭文件。

  4. 正常退出程序或进程。

  5. 行缓冲遇到 \n刷新。

如何改变缓存类型

//与缓冲区相关的一些函数
#include <stdio.h>
void setbuf(FILE *stream, char *buf);
void setbuffer(FILE *stream, char *buf, size_t size);
void setlinebuf(FILE *stream);
​
​
int setvbuf(FILE *stream, char *buf, int mode , size_t size);
参数:
stream:这是指向 FILE 对象的指针,该 FILE 对象标识了一个打开的流。
buffer:这是分配给用户的缓冲。如果设置为 NULL,该函数会自动分配一个指定大小的缓冲。
mode: 这指定了文件缓冲的模式:_IOFBF、_IOLBF、_IONBF。
size:这是缓冲的大小,以字节为单位。
返回值:
如果成功,则该函数返回 0,否则返回非零值。

VScode中的stdout属于无缓冲类型

Ubuntu中的stdout属于行缓冲类型(行缓冲遇到换行符会清空缓冲区,而全缓冲不会)

解释C语言中的volatile关键字并给出应用场景。

  • 答案:volatile 告诉编译器,该变量的值可能随时被外部因素改变,因此禁止优化该变量的读取和写入。

  • 解析:volatile 常用于多线程或硬件寄存器操作等场景,确保每次读取变量时都从内存中获取最新值,避免编译器优化。

  • 补充:

  1. volatile 的作用

    • 禁止优化:编译器通常会对变量进行优化,以提高程序的运行效率。例如,如果某个变量在代码中多次赋值,但是值没有改变,编译器可能会认为这个变量不再被使用,从而优化掉一些访问该变量的代码。但是,当变量是 volatile 类型时,编译器不会做这种优化,确保每次访问变量时都进行实际的读取或写入操作。

    • 外部改变volatile 修饰的变量通常表示该变量的值可以在程序的执行过程中被外部因素(如硬件设备或其他线程)改变。

  2. 常见的应用场景

    • 硬件寄存器:在嵌入式系统编程中,硬件设备的寄存器可能会随时被硬件更改。为了保证对这些寄存器的访问不会被优化掉,通常会用 volatile 修饰寄存器变量。

    • 多线程编程:在多线程程序中,如果一个线程在修改某个变量,而其他线程正在读取该变量,使用 volatile 修饰该变量可以确保每个线程读取到变量的最新值。

如何判断一个链表是否有环?

bool has_cycle(struct ListNode *head) { struct ListNode *slow = head, *fast = head; while (fast && fast->next) { slow = slow->next; fast = fast->next->next; if (slow == fast) return true; } return false; 
} 

如何实现一个 LRU 缓存(Least Recently Used Cache)?

  • 答案:使用双向链表和哈希表结合来实现。哈希表提供快速的访问,双向链表维护访问顺序,当缓存满时,删除最久未使用的元素。

  • 解析:使用双向链表存储数据,哈希表存储键和节点的映射。每次访问数据时,将对应节点移到链表的头部。若缓存满了,删除链表尾部节点。

如何实现一个线程安全的计数器?

  • 答案:使用互斥锁(mutex) 或原子操作来确保多个线程同时访问时不会产生竞态条件。

  • 解析:使用pthread mutex_ t来加锁计数器的修改操作,确保线程安全。也可以使用原子操作(如atomic)来避免锁的开销。

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; 
int counter = 0; 
void increment() { pthread_mutex_lock(&lock); counter++; pthread_mutex_unlock(&lock); 
} 
  • 补充:

std::atomic 是 C++ 提供的一种用于多线程编程的同步原语,保证对数据类型的操作是原子的,即不会被中断或与其他线程产生冲突。它适用于需要在线程之间共享数据而不需要加锁的场景,提供比传统的锁(如 std::mutex)更好的性能。

常用场景 std::atomic 通常用于以下情况:

共享资源的安全访问:在多线程程序中,多个线程需要访问和修改同一变量。 避免锁机制的开销:锁会带来性能上的开销,而 std::atomic 提供了更轻量的原子操作。 简单的同步:当仅需要单个变量的同步时,使用 std::atomic 是非常高效的。

std::atomic 支持的类型 内置基础类型:如 int, bool, char, float, double 等。 自定义类型:可以将自定义结构体/类声明为 std::atomic<T>,但必须保证其满足 "trivially copyable"(平凡可拷贝)要求,即没有自定义构造、析构、拷贝构造和赋值运算符等。

#include <iostream>
#include <atomic>
#include <thread>
​
std::atomic<int> counter(0); // 初始化原子计数器
​
void increment() {for (int i = 0; i < 10000; ++i) {counter.fetch_add(1, std::memory_order_relaxed); // 原子增加}
}
​
int main() {std::thread t1(increment);std::thread t2(increment);
​t1.join();t2.join();
​std::cout << "Final counter value: " << counter << std::endl; // 输出最终的计数器值
​return 0;
}

http://www.lryc.cn/news/2402408.html

相关文章:

  • 宝马集团推进数字化转型:强化生产物流与财务流程,全面引入SAP现代架构
  • 【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 时间事件处理部分)
  • 【DAY40】训练和测试的规范写法
  • C语言 标准I/O函数全面指南
  • el-select 实现分页加载,切换也数滚回到顶部,自定义高度
  • Langchaine4j 流式输出 (6)
  • Jenkins:自动化流水线的基石,开启 DevOps 新时代
  • 学习经验分享【40】目标检测热力图制作
  • C#里与嵌入式系统W5500网络通讯(3)
  • 用OpenNI2获取奥比中光Astra Pro输出的深度图(win,linux arm64 x64平台)
  • Unity VR/MR开发-VR设备与适用场景分析
  • Linux: network: switch:arp cache更新规则 [chatGPT]
  • Java网络编程API 1
  • Android协程学习
  • Angular报错:cann‘t bind to ngClass since it is‘t a known property of div
  • uniapp+vue3实现CK通信协议(基于jjc-tcpTools)
  • Python爬虫实战:研究urlparse库相关技术
  • 解锁FastAPI与MongoDB聚合管道的性能奥秘
  • 软件工程方法论:在确定性与不确定性的永恒之舞中寻找平衡
  • Unity中的MonoSingleton<T>与Singleton<T>
  • 怎么通过 jvmti 去 hook java 层函数
  • 兰亭妙微 | 医疗软件的界面设计能有多专业?
  • 前端原生构建交互式进度步骤组件(Progress Steps)
  • 如何给windos11 扩大C盘容量
  • 【基于阿里云搭建数据仓库(离线)】Data Studio创建资源与函数
  • Linux_T(Sticky Bit)粘滞位详解
  • web3-以太坊智能合约基础(理解智能合约Solidity)
  • 高敏感应用如何保护自身不被逆向?iOS 安全加固策略与工具组合实战(含 Ipa Guard 等)
  • 【C++项目】负载均衡在线OJ系统-2
  • GC1809:高性能24bit/192kHz音频接收芯片解析