嵌入式面经-C语言

本文详细介绍了C语言中静态局部变量、全局变量、extern、volatile、sizeof、strlen、strcpy/memcpy等关键概念,以及数组、指针、回调函数、内存泄漏和溢出、堆栈、分区、编译过程等内容,帮助读者深入理解C语言的基础特性和内存管理技巧。
摘要由CSDN通过智能技术生成

static关键词的作用

  • 修饰局部变量:该变量被称为静态局部变量。静态局部变量在函数调用之间保持其值,并且仅初始化一次。

  • 修饰全局变量:该变量被限制在当前源文件中使用,无法被其他源文件访问。

  • 修饰函数:该函数被限制在当前源文件中使用,无法被其他源文件调用。

extern关键字

  • 声明外部全局变量/函数:当在一个源文件中定义了一个全局变量/函数,希望在其他源文件中也能够访问该变量/函数时,可以使用extern关键字进行声明。这样其他源文件就可以引用该全局变量/函数而不需要重新定义。

volatile关键字的作用

  • 防止编译器优化:编译器为了提高程序的性能,可能会对代码进行优化。在某些场景下,通过将变量声明为volatile,确保每次读取该变量都是最新值,不受编译器优化的影响。

  • 多线程访问同一变量:当多个线程同时访问同一个共享变量时,使用volatile可以确保每次读取和写入该变量时都直接与内存交互,可以避免出现意外行为或数据不一致的情况。

sizeof与strlen

  • sizeof 是关键字,而 strlen 是库函数

  • sizeof 仅用于计算数据类型的大小或者变量的大小,而 strlen 只能以结尾为' \0 '的字符串作为参数

  • sizeof 计算数据类型或变量会占用内存的大小,strlen 计算字符串实际长度(不包括结尾的\0 )

  • 编译器在编译时就计算出了 sizeof 的结果,而 strlen 必须在运行时才能计算出来

strcpy和memcpy

  • 是C语言中用于复制内存内容的函数

  • 参数类型不同

    • strcpy的参数是两个字符串(字符数组),用于将一个字符串复制到另一个字符串中

    • memcpy的参数是两个void指针和一个size_t类型的整数,可以用于任意类型的内存块复制

  • 复制方式不同

    • strcpy会自动在源字符串末尾添加'\0'作为字符串结束标志,然后再进行复制

    • memcpy仅按字节进行逐一复制,没有对数据进行解释或处理

对变量的理解

  • 变量是内存中一块特定的位置,用于保存数据值。通过给变量赋予一个唯一的标识符(变量名),可以在程序中引用这个位置,并对其中存储的数据进行操作。

  • 在使用变量时,需要指定其类型以及初始值

数组和指针

  • 数组

    • 数组是相同类型数据元素的集合,在内存中是连续存储的

    • 数组声明时需要指定元素类型和数组大小

    • 使用索引来访问数组元素,索引从 0 开始

  • 指针与数组

    • 数组名代表了数组首元素的地址,也可以看作一个指向该数组的指针

    • 可以使用指针访问和操作数组中的元素,通过递增指针来遍历整个数组

回调函数

  • 允许将一个函数作为参数传递给另一个函数,并在需要时由另一个函数调用

  • 回调函数通常在异步编程中使用,当某个操作完成或满足特定条件时,会调用预先定义好的回调函数来处理相应的结果或执行相关操作

函数指针和指针函数的区别

  • 函数指针:一个指向函数的指针变量、存储函数的地址,可以用于调用该函数

  • 指针函数:一个返回指针的函数

空指针(NULL)、void *

  • 空指针(NULL)是一个特殊的指针值,表示指针不指向任何有效的内存地址

  • void * 可以表示任意类型的指针

结构体和联合体之间的区别

  • 结构体

    • 结构体将不同类型的数据组合成一个整体,每个成员都有自己独立的内存空间,所有成员的值可以同时存在

    • 结构体的大小通常等于其所有成员大小的总和

    • 使用 struct 关键字来声明结构体,然后定义结构体的成员

  • 联合体

    • 联合体将不同类型的数据放在同一块内存空间中,同一时刻只有一个成员可以被访问

    • 联合体的大小则等于其最大成员的大小

    • 使用 union 关键字来声明联合体,然后定义联合体的成员

  • 结构体和联合体内都可以定义不同类型的数据

内存泄漏和内存溢出

  • 内存泄漏:在程序运行过程中,动态分配的内存空间没有被正确回收。这种情况下,当不再需要使用这块内存时,无法再访问到它,导致这块内存变得无法被重新利用。

  • 内存溢出:尝试向已经分配满了的内存区域写入数据,会覆盖到其他变量、代码和数据结构等

堆和栈的区别

  • 堆和栈是计算机内存中用于管理变量和数据的两种不同的存储区域

  • 内存分配方式

    • 栈采用静态内存分配,由编译器自动管理。

    • 堆采用动态内存分配,需要手动进行申请与放。

  • 空间大小

    • 栈空间通常较小,具有固定的大小,并且通过函数调用层级来管理变量的生命周期。

    • 堆空间相对较大,没有固定大小限制,可以灵活地进行内存分配。

  • 内存管理方式

    • 栈由编译器自动进行变量的分配和释放,在函数结束时会自动回收局部变量所占用的栈空间。

    • 堆则需要手动进行内存的申请(如malloc、new等)和释放(如free、delete等),否则会出现内存泄漏问题。

  • 数据访问速度

    • 栈上的数据访问速度较快,因为它使用了先进后出(LIFO)的原则,并且位于CPU高速缓存中。

    • 堆上分配的数据访问速度较慢,因为它不是按照顺序进行分配。

分区

  • 栈区

    • 是编译器自动分配和释放

    • 里面主要放函数的参数,普通的局部变量等

  • 堆区

    • 是程序员通过 new 和 molloc 函数去分配的,对应 delect 和 free 函数回收

    • 里面具体放啥由程序员决定

  • 常量区:放置常量,不允许更改

  • 代码区:放代码块,在代码运行的时候不能更改

  • 静态区

    • 放全局变量和被 static 修饰的局部变量

    • 根据是否初始化

      • Bss 区:表示编译器没有为其分配空间、没赋初值的

      • data 区:赋初值的

大小端模式

  • 字节的顺序是从高位到低位(大端)还是从低位到高位(小端)

  • 大端对齐:低地址存放高位、高地址存放低位

  • 小端对齐:低地址存放低位、高地址存放高位

C语言的编译过程

  • 预处理:对源代码进行处理,展开头文件、宏定义,并去除注释等。生成的纯C代码文件。

  • 编译:编译器将预处理后的源代码转化为汇编语言(.s文件)

  • 汇编:汇编器将汇编语言代码转化为机器码指令,即可执行的二进制文件(.o文件)。

  • 链接:链接器将所有需要用到的函数库和对象文件合并成一个可执行文件(.exe文件)。

  • 15
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SMC嵌入软件面经主要涉及以下几个方面。 首先,针对嵌入软件开发的基础知识进行了深入的考查。在面试中,我被问到了如何进行嵌入软件的开发流程、如何进行嵌入系统的调试以及如何进行嵌入操作系统的选择。我回答了嵌入软件开发的基本流程,包括需求分析、系统设计、编码实现和测试验证等步骤。同时,我还解释了如何通过调试工具对嵌入系统进行调试,并且讨论了选择嵌入操作系统时要考虑的因素。 其次,面试中还涉及到了嵌入软件开发中的具体技术和工具的应用。我被问到了对于C语言和汇编语言的掌握程度以及使用嵌入软件开发工具的经验等。我解答了自己对于C语言和汇编语言的熟悉程度,并强调了在嵌入软件开发中使用调试器、编译器、仿真器等工具的重要性。 最后,在面试中还进行了一些关于嵌入软件开发项目经验的讨论。这些问题包括我在以前的项目中遇到的困难和解决的方法、团队合作的经验以及自我学习和成长的能力等。我详细介绍了我在以前的项目中所遇到的困难,如何与团队成员合作,并提出了自己学习和提升的策略。 综上所述,SMC嵌入软件面经主要涉及嵌入软件开发的基础知识、具体技术和工具的应用以及项目经验等方面。在面试中,我对这些问题进行了详细的回答,并强调了自己的实践经验和学习能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值