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

嵌入式面试八股文·C语言高频面经(一)

在这里插入图片描述

目录

  • 1. 全局变量和局部变量的区别
    • 1.1 全局变量
    • 1.2 局部变量
  • 2. 内存布局
  • 3. static关键字
  • 4. const关键字
  • 5. const 和 #define的区别
  • 6. extern关键字
  • 7. #include<> 和 #include""的区别
    • 7.1 使用 #include<>
    • 7.2 使用 #include""
  • 8. 头文件#ifndef/#define/#endif的作用
  • 9. volatile声明的作用
  • 10. strcpy与memcpy的区别
    • 10.1 strcpy
    • 10.2 memcpy
  • 11. 数组名与指针的区别
    • 11.1 数组名
    • 11.2 指针
  • 12. 结构体和共用体的区别
    • 12.1 结构体
    • 12.2 共用体
  • 13. 数组指针与指针数组的区别
    • 13.1 数组指针(pointer to an array)
    • 13.2 指针数组(array of pointers)
  • 14. 指针函数与函数指针的区别
    • 14.1 指针函数(function returning a pointer)
    • 14.2 函数指针(pointer to a function)
  • 15. 原码、反码、补码的定义
  • 16. malloc和calloc的区别
    • 16.1 malloc
    • 16.2 calloc
  • 17. 在1G内存的计算机中能否malloc(1.2G)?为什么?
  • 18. 简述内存泄漏,如何检测和避免?
    • 18.1 常见内存泄露情况
    • 18.2 检测内存泄漏
    • 18.3 避免内存泄漏:
  • 19. (内存)堆和栈的区别
    • 19.1 堆栈空间分配不同
    • 19.2 堆栈缓存方式不同
    • 19.3 生长方向
    • 19.4 生命周期:
    • 19.5 空间大小
    • 19.6 能否产生碎片
  • 20. 在函数中申请堆内存需要注意什么
  • 21. 请你说说内存碎片
  • 22. 什么是内存池
  • 23. 为什么需要内存池?
  • 24. 初始化为0的全局变量在bss还是data
  • 25. 使用指针需要注意什么?

1. 全局变量和局部变量的区别

1.1 全局变量

① 在函数外部声明的变量,整个程序都可以访问;
② 声明时会被默认初始化,可以在任何函数中使用;
③ 生命周期长,整个程序执行期间都存在;
④ 全局变量存储在全局数据区(data)中。

1.2 局部变量

① 在函数内部或代码块内部声明的变量,只能在所属的函数或代码块中访问;
② 声明时没有默认初始化,需要手动赋值才能使用;
③ 生命周期短,只在所属的函数或代码块的执行期间存在;
④ 局部变量存储在栈区(stack)。

2. 内存布局

代码段(Text Segment):存储程序的机器码,通常是只读的,因为程序的指令在执行过程中不应该被修改。
数据段(Data Segment):存储已初始化的全局变量和静态变量,这些变量在程序开始运行时已经赋予了初始值。
BSS段(Block Started by Symbol):存储未初始化的全局变量和静态变量,它们在程序开始运行时会自动初始化为0或者空指针。
堆(Heap):用于动态内存分配,用于存放程序运行时动态申请的内存。(程序员可以通过函数(如malloc、calloc等)或者操作系统提供的接口来申请和释放堆内存,堆从低地址向高地址增长。)
栈(Stack):存放函数的局部变量、函数参数值以及函数调用和返回时的相关信息。栈区是按照“先进后出”的原则进行管理,内存的分配和释放是自动进行的,栈从高地址向低地址增长。是一块连续的空间。
共享区:也称为文件映射或共享内存,用于实现不同进程之间的内存共享。
在这里插入图片描述

3. static关键字

① 声明静态变量,使其生命周期延长或作用域限定在当前文件内;
② 声明静态函数,使其作用域限定在当前文件内;
③ 声明静态成员变量,使其属于类本身而不是对象,多个对象共享同一份内存;
④ 使用静态限定符,控制变量的初始化和生命周期。

4. const关键字

① 值不可修改:一旦常量被赋值后,其值将保持不变,不能再对其进行修改;
② 作用域限制:常量的作用域通常被限制在声明时所在的作用域内部;
③ 编译时确定:常量的值在编译时就已确定,并在运行时保持不变。

5. const 和 #define的区别

① const是一种编译器关键字,而#define是预处理器指令。const在编译阶段进行处理,而#define在预处理阶段进行处理;
② const定义的常量具有类型,而#define没有。const在声明时需要指定常量的类型,编译器会进行类型检查。而#define只是简单的文本替换,没有类型检查;
③ const定义的常量有作用域限制,可以根据声明位置的不同而有不同的作用域。而#define定义的常量没有作用域限制,整个程序中都有效;
④ const生成符号表中的一个符号,有明确的名字和类型,可以进行调试和符号查找。而#define没有生成符号表,不会产生对应的符号。

6. extern关键字

① 声明一个在其他文件中定义的外部变量或函数;
② 告诉编译器在链接过程中需要找到对应的定义;
③ 允许在当前文件中使用这些外部变量或函数而不需要重新定义。

7. #include<> 和 #include""的区别

7.1 使用 #include<>

① 用于包含系统提供的标准库头文件;
② 在编译器的搜索路径中寻找头文件;
③ 编译器会先在系统的标准头文件目录中查找,如果找不到则报错。

7.2 使用 #include""

① 用于包含用户自定义的头文件或项目中使用的其他非系统头文件;
② 在当前源文件的相对路径或指定的绝对路径中寻找头文件;
③ 编译器会首先在当前源文件所在目录中查找,如果找不到再根据指定的路径查找。

8. 头文件#ifndef/#define/#endif的作用

① #ifndef:用于判断当前头文件是否已经被包含。如果该宏之前没有被定义过,则继续编译下面的代码。如果该宏之前已被定义过,则跳过下面的代码,直接到 #endif;
② #define:用于定义一个宏。通过定义一个特定的宏名称,例如MY_HEADER_H表示头文件已被包含;
③ #endif:用于结束 #ifndef / #define / #endif 块。标记了头文件的结束位置。

#ifndef MYHEADER_H     // 如果 MYHEADER_H 还没有被定义
#define MYHEADER_H     // 定义 MYHEADER_H

void sayHello();       // 函数声明

const int MAX_VALUE = 100;  // 常量定义

#endif               // 结束条件编译

9. volatile声明的作用

volatile声明的变量是指可能会被意想不到地改变的变量,这样编译器就不会轻易优化该变量。它主要用于多线程编程中,用来保证共享变量的内存可见性。(注:指针也可用volatile)
三个常见场景:
① 多线程中的共享变量
② 中断程序中访问到的非自动变量
③ 并行设备的硬件寄存器

10. strcpy与memcpy的区别

10.1 strcpy

① 用于字符串拷贝。
② 源字符串中的内容会被复制到目标字符串中,直到遇到字符串结束符 ‘\0’。
③ 目标字符串必须有足够的空间来存储被复制的内容,否则可能导致缓冲区溢出。

10.2 memcpy

① 用于字节级别的内存拷贝。
② 可以拷贝任意类型的内存块,不仅限于字符串。
③ 不会检查字符串结束符,通过指定要拷贝的字节数进行拷贝。
④ 可以用于拷贝部分或完整的数组、结构体等。

11. 数组名与指针的区别

11.1 数组名

① 是一个常量指针,指向数组的首元素。
② 大小固定为整个数组的大小。
③ 无法被改变或重新赋值。
④ 无法进行指针运算。

11.2 指针

① 是一个变量,存储一个内存地址。
② 大小固定为指针类型的大小。
③ 可以指向任意类型的对象。
④ 可以被改变或重新赋值。
⑤ 可以进行指针运算,如加法、减法等。

12. 结构体和共用体的区别

12.1 结构体

① 成员在内存中独立存储,每个成员占用独立的内存空间。
② 内存占用是成员之和,每个成员都占用独立的空间。
③ 成员可以同时被访问,通过成员名字来访问。
④ 适合存储和处理多个不同类型的数据,如员工信息、图形对象等。

12.2 共用体

① 成员共享同一块内存空间,只能存储一个成员的值。
② 内存占用是最大成员的大小,


http://www.kler.cn/a/562467.html

相关文章:

  • 【leetcode】二分算法模板总结
  • 深入理解HTTP Basic认证与Java实现
  • 2 Text2SQL 智能报表方案介绍
  • 【Qt】桌面应用开发 ------ 绘图事件和绘图设备 文件操作
  • 软件安全测评报告内容和作用简析,如何获取权威安全测评报告?
  • 3DGS(三维高斯散射)与SLAM技术结合的应用
  • 使用内置命令查看笔记本电池健康状态
  • 【第三天】零基础学习量化基础代码分析-持续更新
  • Unity百游修炼(3)——Tank_Battle(双人对战)详细制作全流程
  • HTML邮件的制作以及可能遇到的问题
  • 【LeetCode20】有效的括号
  • LeetCodeHot100_0x02
  • Fisher散度:从信息几何到机器学习的隐藏利器
  • QT MD5校验文件和数据的完整性
  • 国内访问Github的四种方法(2025版)
  • 堆排序:高效的选择排序
  • selenium如何实现,开启浏览器的开发者工具模式,并且开启 toggle移动设备模拟模式
  • 视频编解码技术-3: H.264和VP9压缩效率和编码时延
  • Ubuntu22上安装MySQL8启动成功,远程无法连接
  • vue2中,打包报错ERROR in /node_modlules/@types/lodash/common/common.d.ts 26