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

面经--C语言——static,volatile,malloc,使用异或进行数据交换

文章目录

    • static静态变量和全局变量的区别
    • volatile
      • 主要作用
    • malloc
      • 1. 内存分配器的作用
      • 2. 内存分配过程
        • (1) 查找空闲内存块
        • (2) 扩展堆空间
        • (3) 元数据
      • 3. 内存释放过程
        • (1) 标记为可用
        • (2) 合并相邻空闲块
        • (3) 延迟释放
      • 4. 内存管理策略
        • (1) 分配缓存(Allocation Caching)
        • (2) 延迟释放(Lazy Freeing)
        • (3) 内存对齐
        • (4) 分配器锁(Allocator Locking)
    • 使用宏函数进行数据交换(不使用中间变量)
      • 宏函数:
      • 原理分析:
      • 为什么使用 `do...while(0)`:

static静态变量和全局变量的区别

区别全局变量static静态变量
作用域整个源文件,任何地方都可以访问到。仅限于声明它的源文件,不能被其他文件访问。
链接性外部链接性,可以被其他文件访问,所有文件中的实例相同。内部链接性,只能在声明它的源文件中访问。
初始化可以显式初始化,未显式初始化时,默认为零值(静态存储期)或未定义值(动态存储期)。(静0动未知)可以显式初始化,未显式初始化时,默认为零值或用户指定的初始值。
生命周期具有静态存储期,生命周期从程序启动到结束,值在函数调用之间保持。同左

volatile

它的主要作用是告诉编译器,这个变量的值可能会被程序之外的因素修改,因此编译器不应对它进行优化。这样,编译器会确保每次访问该变量时都从内存中读取其最新值,而不是使用寄存器中的缓存值。

主要作用

  1. 防止优化
    编译器会在代码中进行一些优化,例如将某些变量的值缓存到寄存器中,以提高性能。但是,volatile 告诉编译器不要这么做,因为这个变量的值可能会被外部事件或硬件等修改。这样,编译器每次访问该变量时都会直接从内存中读取值。

  2. 适用于硬件寄存器
    在嵌入式编程中,volatile 常常用于表示与硬件寄存器或传感器相关的变量。由于硬件的状态会随时发生变化,编译器不应该对这些变量进行优化。

  3. 适用于多线程编程
    在多线程编程中,volatile 可以用于共享变量,确保线程之间读取的是最新的值。尽管如此,在现代多线程编程中,volatile 不能代替更强的同步机制(如互斥锁或原子操作),因为它不能保证变量访问的原子性。

malloc

malloc 是 C 语言中用于动态分配内存的标准库函数,它通过内存分配器来管理程序的堆内存。

1. 内存分配器的作用

malloc 函数背后依赖的内存分配器负责管理程序的堆内存。内存分配器维护了一个可用内存块的列表,并负责动态分配和回收内存。常见的内存分配器有:

  • 基于链表的分配器:如 ptmalloc(在 Linux 中广泛使用)使用链表来管理内存块。
  • 堆管理器:堆内存管理器通过多种方式维护堆空间,以优化内存分配的效率。

内存分配器的目标是尽量避免内存碎片化,并提高内存分配与回收的速度。

2. 内存分配过程

当你调用 malloc(size) 请求分配一块指定大小的内存时,内存分配器会按照以下步骤进行操作:

(1) 查找空闲内存块
  • 内存分配器会在已分配的内存块列表中查找是否有一个足够大的空闲内存块,满足要求的大小 (size)。
  • 如果找到合适的内存块,分配器将其从空闲列表中移除,并返回该内存块的起始地址。
(2) 扩展堆空间
  • 如果没有找到合适的空闲块,内存分配器会向操作系统请求更多的内存。常见的系统调用有:

    • brk():通过改变程序的堆顶指针来扩展堆。通常只适用于较早的 UNIX 系统。
    • mmap():通过映射新的内存区域来扩展堆,适用于更现代的操作系统。

    扩展堆的过程会将一块新的内存区域分配给程序,用来满足 malloc 的请求。

(3) 元数据

分配的内存块通常包含一些额外的元数据,通常存储如下信息:

  • 内存块的大小:用于在释放时检查该内存块的大小。
  • 分配状态:标记该内存块是已分配还是空闲。
  • 内存对齐:为了提高内存访问效率,内存块的起始地址通常是对齐的。

3. 内存释放过程

当调用 free(ptr) 时,内存分配器将释放之前通过 malloc 分配的内存块。释放的过程大致如下:

(1) 标记为可用
  • free 会将内存块标记为“空闲”,即这块内存可以被重新分配给其他请求。
(2) 合并相邻空闲块
  • 内存分配器通常会检查相邻的内存块,如果相邻的内存块也是空闲的,它们会被合并成一个较大的空闲块,从而减少内存碎片化现象。
(3) 延迟释放
  • 对于常见的内存分配器,内存释放并不会立即返回给操作系统,而是留在堆中以备将来使用。这样可以提高后续内存分配的效率。

4. 内存管理策略

内存分配器通常会实现一系列策略来优化内存分配和释放的性能,主要包括:

(1) 分配缓存(Allocation Caching)
  • 内存分配器通常会为小块内存分配设置缓存池(例如 malloc 用于小对象时会使用缓存),减少频繁的操作系统调用,提高内存分配的效率。
(2) 延迟释放(Lazy Freeing)
  • 内存分配器并不会在每次 free 后立即返回内存给操作系统,而是将内存块保留在堆中。这有助于避免频繁的系统调用,从而提高性能。
(3) 内存对齐
  • 为了提高 CPU 访问效率,内存分配器会确保分配的内存块是对齐的。例如,分配的内存块可能会对齐到 8 字节或 16 字节边界。
(4) 分配器锁(Allocator Locking)
  • 在多线程环境下,为了防止多个线程同时访问内存分配器而导致竞争条件,内存分配器通常会使用锁机制(如互斥锁)来保证内存分配的线程安全性。

使用宏函数进行数据交换(不使用中间变量)

在 C 语言中,我们可以通过宏函数来实现一些操作,甚至可以通过运用位运算来优化代码,避免使用额外的变量。下面介绍如何利用**异或(XOR)**操作来交换两个变量的值,而不使用中间变量。

宏函数:

#define SWAP_NO_TEMP(a, b) do {  \(a) ^= (b);                  \(b) ^= (a);                  \(a) ^= (b);                  \
} while (0)

原理分析:

我们知道异或操作的一个重要性质:

  1. A ⊕ A = 0 A \oplus A = 0 AA=0(同样的数进行异或得到0)
  2. A ⊕ 0 = A A \oplus 0 = A A0=A(任何数与0异或还是它本身)

基于这一性质,异或操作可以用来交换两个数的值。下面逐步分析这个宏函数的工作原理:

  1. 第一步a ^= b;

    • 这一步是将ab进行异或运算,结果保存在a中。将a和b的不同位设为1。
  2. 第二步b ^= a;

    • 现在b被更新为b ^ (a ^ b),可以根据异或的结合性简化为a,即b变成了原来的a值。任何数异或1都为相反的值,任何数异或0都为它自身。
  3. 第三步a ^= b;

    • 最后,此时b为原来的a值,a为原来的a和b,不相同为1,相同为0,a被更新为(a ^ b) ^ a,这个运算结果为原来的b值。

经过这三步操作,ab的值就成功交换了。

为什么使用 do...while(0)

  • 这确保了宏函数的语法可以作为一个单独的语句块存在。do...while(0)结构是为了确保宏可以像函数一样正常工作,避免由于宏展开带来的潜在问题。这样即使在if语句中使用宏,也不会引发意外的错误(比如漏写花括号)。

相关文章:

面经--C语言——static,volatile,malloc,使用异或进行数据交换

文章目录 static静态变量和全局变量的区别volatile主要作用 malloc1. 内存分配器的作用2. 内存分配过程(1) 查找空闲内存块(2) 扩展堆空间(3) 元数据 3. 内存释放过程(1) 标记为可用(2) 合并相邻空闲块(3) 延迟释放 4. 内存管理策略(1) 分配缓存(Allocation Caching…...

stm32小白成长为高手的学习步骤和方法

我们假定大家已经对STM32的书籍或者文档有一定的理解。如不理解,请立即阅读STM32的文档,以获取最基本的知识点。STM32单片机自学教程 这篇博文也是一篇不错的入门教程,初学者可以看看,讲的真心不错。 英文好的同学&#xf…...

OSCP - Proving Grounds - Roquefort

主要知识点 githook 注入Linux path覆盖 具体步骤 依旧是nmap扫描开始,3000端口不是很熟悉,先看一下 Nmap scan report for 192.168.54.67 Host is up (0.00083s latency). Not shown: 65530 filtered tcp ports (no-response) PORT STATE SERV…...

集合通讯概览

(1)通信的算法 是根据通讯的链路组成的 (2)因为通信链路 跟硬件强相关,所以每个CCL的库都不一样 芯片与芯片、不同U之间是怎么通信的!!!!!! 很重要…...

【贪心算法篇】:“贪心”之旅--算法练习题中的智慧与策略(二)

✨感谢您阅读本篇文章,文章内容是个人学习笔记的整理,如果哪里有误的话还请您指正噢✨ ✨ 个人主页:余辉zmh–CSDN博客 ✨ 文章所属专栏:贪心算法篇–CSDN博客 文章目录 前言例题1.买卖股票的最佳时机2.买卖股票的最佳时机23.k次取…...

oracle: 表分区>>范围分区,列表分区,散列分区/哈希分区,间隔分区,参考分区,组合分区,子分区/复合分区/组合分区

分区表 是将一个逻辑上的大表按照特定的规则划分为多个物理上的子表,这些子表称为分区。 分区可以基于不同的维度,如时间、数值范围、字符串值等,将数据分散存储在不同的分区 中,以提高数据管理的效率和查询性能,同时…...

基于SpringBoot 前端接收中文显示解决方案

一. 问题 返回给前端的的中文值会变成“???” 二. 解决方案 1. 在application.yml修改字符编码 (无效) 在网上看到说修改servlet字符集编码,尝试了不行 server:port: 8083servlet:encoding:charset: UTF-8enabled: trueforce: true2. …...

java练习(5)

ps:题目来自力扣 给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。 请你将两个数相加,并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外,这…...

python算法和数据结构刷题[3]:哈希表、滑动窗口、双指针、回溯算法、贪心算法

回溯算法 「所有可能的结果」,而不是「结果的个数」,一般情况下,我们就知道需要暴力搜索所有的可行解了,可以用「回溯法」。 回溯算法关键在于:不合适就退回上一步。在回溯算法中,递归用于深入到所有可能的分支&…...

大数据数仓实战项目(离线数仓+实时数仓)1

目录 1.课程目标 2.电商行业与电商系统介绍 3.数仓项目整体技术架构介绍 4.数仓项目架构-kylin补充 5.数仓具体技术介绍与项目环境介绍 6.kettle的介绍与安装 7.kettle入门案例 8.kettle输入组件之JSON输入与表输入 9.kettle输入组件之生成记录组件 10.kettle输出组件…...

【开源免费】基于Vue和SpringBoot的公寓报修管理系统(附论文)

本文项目编号 T 186 ,文末自助获取源码 \color{red}{T186,文末自助获取源码} T186,文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…...

使用QMUI实现用户协议对话框

使用QMUI实现用户协议对话框 懒加载用于初始化 TermServiceDialogController 对象。 懒加载 lazy var 的作用 lazy var dialogController: TermServiceDialogController {let r TermServiceDialogController()r.primaryButton.addTarget(self, action: #selector(primaryC…...

女生年薪12万,算不算属于高收入人群

在繁华喧嚣的都市中,我们时常会听到关于收入、高薪与生活质量等话题的讨论。尤其是对于年轻女性而言,薪资水平不仅关乎个人价值的体现,更直接影响到生活质量与未来的规划。那么,女生年薪12万,是否可以被划入高收入人群…...

初识Cargo:Rust的强大构建工具与包管理器

初识Cargo:Rust的强大构建工具与包管理器 如果你刚刚开始学习Rust,一定会遇到一个名字:Cargo。Cargo是Rust的官方构建工具和包管理器,它让Rust项目的创建、编译、测试和依赖管理变得非常简单。本文将带你快速了解Cargo的基本用法…...

【Windows7和Windows10下从零搭建Qt+Leaflet开发环境】

Windows7和Windows10下从零搭建QtLeaflet开发环境 本文开始编写于2025年1月27日星期一(农历:腊月二十八,苦逼的人,过年了还在忙工作)。 第一章 概述 整个开发环境搭建需要的资源: 操作系统 Windows7_x6…...

关于MySQL InnoDB存储引擎的一些认识

文章目录 一、存储引擎1.MySQL中执行一条SQL语句的过程是怎样的?1.1 MySQL的存储引擎有哪些?1.2 MyIsam和InnoDB有什么区别? 2.MySQL表的结构是什么?2.1 行结构是什么样呢?2.1.1 NULL列表?2.1.2 char和varc…...

WSL2中安装的ubuntu开启与关闭探讨

1. PC开机后,查询wsl状态 在cmd或者powersell中输入 wsl -l -vNAME STATE VERSION * Ubuntu Stopped 22. 从windows访问WSL2 wsl -l -vNAME STATE VERSION * Ubuntu Stopped 23. 在ubuntu中打开一个工作区后…...

LeetCode435周赛T2贪心

题目描述 给你一个由字符 N、S、E 和 W 组成的字符串 s,其中 s[i] 表示在无限网格中的移动操作: N:向北移动 1 个单位。S:向南移动 1 个单位。E:向东移动 1 个单位。W:向西移动 1 个单位。 初始时&#…...

π0:仅有3B数据模型打通Franka等7种机器人形态适配,实现0样本的完全由模型自主控制方法

Chelsea Finn引领的Physical Intelligence公司,专注于打造先进的机器人大模型,近日迎来了一个令人振奋的里程碑。在短短不到一年的时间内,该公司成功推出了他们的首个演示版本。这一成就不仅展示了团队的卓越技术实力,也预示着机器…...

DeepSeek-R1 低成本训练的根本原因是?

在人工智能领域,大语言模型(LLM)正以前所未有的速度发展,驱动着自然语言处理、内容生成、智能客服等众多应用的革新。然而,高性能的背后往往是高昂的训练成本,动辄数百万美元的投入让许多企业和研究机构望而…...

pandas(二)读取数据

一、读取数据 示例代码 import pandaspeople pandas.read_excel(../002/People.xlsx) #读取People数据 print(people.shape) # 打印people表的行数、列数 print(people.head(3)) # 默认打印前5行,当前打印前3行 print("") print(people.tail(3)) # 默…...

北京门头沟区房屋轮廓shp的arcgis数据建筑物轮廓无偏移坐标测评

在IT行业中,地理信息系统(GIS)是用于处理、分析和展示地理空间数据的重要工具,而ArcGIS则是GIS领域中的一款知名软件。本文将详细解析标题和描述中提及的知识点,并结合“门头沟区建筑物数据”这一标签,深入…...

【自学笔记】Java的重点知识点-持续更新

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 Java知识点概览一、Java简介二、Java基本语法三、面向对象编程(OOP)四、异常处理五、常用类库六、多线程编程七、网络编程 注意事项 总结 Ja…...

向上调整算法(详解)c++

算法流程: 与⽗结点的权值作⽐较,如果⽐它⼤,就与⽗亲交换; 交换完之后,重复 1 操作,直到⽐⽗亲⼩,或者换到根节点的位置 这里为什么插入85完后合法? 我们插入一个85,…...

LabVIEW无线齿轮监测系统

本案例介绍了基于LabVIEW的无线齿轮监测系统设计。该系统利用LabVIEW编程语言和改进的天牛须算法优化支持向量机,实现了无线齿轮故障监测。通过LabVIEW软件和相关硬件,可以实现对齿轮箱振动信号的采集、传输和故障识别,集远程采集、数据库存储…...

用deepseek解决python问题——在cmd终端运行python指令弹出应用商店,检查路径已经加入环境变量

首先上结论:可行性非常强 当然我没有广泛对比,至少豆包解决方案基本上就是网络上能搜到的一些方法,没有帮我解决,下面直接看一下对话吧 我:在cmd运行python指令弹出应用商店,检查路径已经加入环境变量 D…...

力扣第435场周赛讲解

文章目录 题目总览题目详解3442.奇偶频次间的最大差值I3443.K次修改后的最大曼哈顿距离3444. 使数组包含目标值倍数的最少增量3445.奇偶频次间的最大差值 题目总览 奇偶频次间的最大差值I K次修改后的最大曼哈顿距离 使数组包含目标值倍数的最少增量 奇偶频次间的最大差值II …...

内存四区

一、内存四区模型 1. 操作系统把物理硬盘代码load到内存 2. 操作系统把c代码分成四个区 3. 操作系统遭到main函数入口执行 二、内存四区 1. 栈区(stack) 由编译器自动分配释放,存放函数的参数值,局部变量的值。其操作方式类似…...

大模型综合性能考题汇总

- K1.5长思考版本 一、创意写作能力 题目1:老爸笑话 要求:写五个原创的老爸笑话。 考察点:考察模型的幽默感和创意能力,以及对“原创”要求的理解和执行能力。 题目2:创意故事 要求:写一篇关于亚伯拉罕…...

Python - pyautogui库 模拟鼠标和键盘执行GUI任务

安装库: pip install pyautogui 导入库:import pyautogui 获取屏幕尺寸: s_width, s_height pyautogui.size() 获取鼠标当前位置: x, y pyautogui.position() 移动鼠标到指定位置(可以先使用用上一个函数调试获取当…...