嵌入式校招_面试经验大全【C语言】【1_变量】

【以下内容,后续会不断更新补充!】

各位同学有想看某一个知识点详细解析的,也可以在评论区留言~

目录

【专栏一】嵌入式校招指南

作者机械硕士,从零开始自学嵌入式软件,21届秋招进入国内芯片大厂。

从自身转行经历来看,网上嵌入式学习路线的资料少之又少,大多千篇一律且复制粘贴。

而嵌入式入行门槛高,技能树要求多,学习难度非常大,没有有效的方法指导,很容易迷失方向,错过校招。

在此专栏分享我的校招从零开始转行经验,听我给你娓娓道来~

专栏链接 https://www.nowcoder.com/creation/manager/columnDetail/MWZkkj

1.专栏大纲&写在前面

2.转行概述

3.前期准备

4.自学教材推荐_基础知识

5.自学教材推荐_笔试准备

6.开发板&项目

7.简历

8.行业&公司

9.城市&岗位

10.消费&工业电子类公司

未完待续……

【专栏二】嵌入式校招_面试经验大全

嵌入式软件校招的常见问题,应付校招面试的速效救心丸,你值得拥有!

嵌入式的知识太多太杂,不知道面试经常问哪些? 书上说的知识点太抽象,没有一定的基础很难理解?

别怕,本专栏用通俗的语言和比喻,为你讲清楚!

包含C语言、计算机组成原理、操作系统、数据结构与算法及计算机网络等,详见大纲。

1.【C语言】【1_变量】https://www.nowcoder.com/discuss/491773863525679104

2.【C语言】【2_关键字】https://www.nowcoder.com/discuss/497562309628276736

3.【C语言】【3_数据结构&位运算】https://www.nowcoder.com/discuss/505894349847224320

一、变量&位运算

【问】介绍一下全局变量和局部变量

【答】

C语言中所有变量都有作用域,区别在于变量定义在C文件中的位置。

  • 全局变量

全局变量的作用域是整个程序,可以被程序中的任何函数访问。

通常在C文件头部定义,程序启动时就分配好,在程序运行期间一直存在于内存的全局数据区

  • 局部变量
  • 局部变量的作用域仅限于所在函数内部,不能被其他函数访问。

    在函数被调用时才会被创建,在函数结束时被销毁。

    【解析】

    【考察点】变量的作用域

    全局变量就是公共资源,所有人(函数)都能看到,都能拿来用。

    局部变量就是私人财产,仅限本人(当前函数)使用。

    全局变量若加上static关键字,则作用域就变成仅限当前C文件可调用。

    全局变量和局部变量同名时,局部变量生效。

    形参变量也是局部变量,实参给形参传值就是给局部变量赋值。

    局部变量有两种创建方式:

    • 在函数开头定义的变量(数据,数组等),程序运行时自动创建在内存的中,在函数结束后(return后)自动销毁。
    • 在程序中显式地使用malloc()等函数来申请,存放在内存的中,必须手动调用free函数来释放(否则会导致内存泄漏)。

    【问】Float类型怎么判断是否为0

    【答】

    const float EPSINON = 0.000001;

    if ((TestNum >= - EPSINON) && (TestNum <= EPSINON)

    printf("TestNum equal to 0!");

    else

    printf("TestNum not equal to 0!");

    【解析】

    【考察点】float类型变量的大小比较

    • float存储方式

    float类型占4Byte即32bit,包括1bit符号位、8bit二进制指数和一个23bit尾数。

    浮点数存储标准可以查看IEEE754标准。

    首先我们都知道,科学计数法是将所有的数字记为(±)A.B * 10^C 的形式。

    但是由于数据在计算机中都是以二进制存储,所以float需转为(±)1.B * 2^C 的形式。

    因此,float将4Byte(32bit)分为1、8和23bit共3部分,来表示符号(±)、B和C储存。

    符号位(1bit)。0表示正数,1表示负数。

    指数部分(8bit)。存储了上文的C+127(特殊算法,理解为指数部分就是为了存储C即可)。

    尾数部分(23位)。上文中提到的数字B。

    总结下来,float类型可以保证包括整数位在内的7位有效数字是准确。

    • EPSINON

    EPSINON是很小的值,因为float型只能精确到小数点后六位,即1e-6。

    将float型的TestNum与1e-6比较,若比1e-6小则为零。

    小数六位以后是没有意义,如数0.0000001虽然不等于零,但是第七位小数1是没有意义的则认为这个数等于0。

    【问】int型变量是多少位?

    【答】根据当前CPU架构是多少位决定的。

    按照C语言定义,int必须介于short跟long之间,也就是说它必须介于16位跟64位之间。

    int类型具体占用多少位,与当前CPU架构相关。多少位的CPU则代表着int类型占据多少位。

    比如在16位51单片机的C代码中,int代表2个字节(16位);32位RAM处理器的C代码中,int代表4个字节(32位)64位的RAM64处理器中,则int是8个字节(64位)。

    【解析】

    【考察点】变量占据的bit大小与CPU架构的关系

    • 在32 位的系统上

    short类型占2个byte;

    int类型占4个byte;

    long类型占4个byte;

    float类型占4个byte;

    double类型占8个byte;

    char类型占1个byte。

    • 可以用sizeof(int)测试一下当前系统下的int类型长度。
    • 使用建议

    对于长度敏感的变量,建议包含该头文件:include stdint.h

    然后使用固定长度如uint32_t(32位的unsigned int)、uint64_t这样的显式类型。

    这样的类型定义,可以直接跨平台使用,不用担心移植过程中出错~

    而对长度不敏感的变量(如for循环中的i),直接用int即可。

    • 指针类型也会占用空间,同样和CPU架构有关。但是具体的细节不太一样,详见后续指针章节。

    【问】*char型变量最大能表示的值?如果超出最大值怎么处理?

    【答】 char型变量是8位,共能表示2^8=256个数值。

    • 其中无符号的unsigned char,能表示0~2^8-1,也就是0-255
  • 有符号的char型变量,-128到127之间的整数值。其中的最高位为符号位,0表示正数,1表示负数。
    • char型变量超出最大值后的具体计算方法:

    加法溢出的计算方法:溢出值 - 256。

    减法溢出的计算方法:溢出值+256。

    【考察点】"char变量所能表示数值的范围"

    以下有符号的signed char简称为char,无符号的unsigned char简称为uchar

    【前提】【重要】:无论什么类型的数值(char、int),无论有符号或无符号,在计算机中都是以"二进制"的形式储存,读取的时候会根据该数值的类型来"翻译"成指定类型(uchar、int、uint)。

    可以把uchar看作是2^8=256个刻度的钟表,从0到255。+1表示顺时针走一个刻度,-1表示逆时针走一个刻度。当达到它能表示的最大值256时,会重新从0开始计数。

    • 举个栗子:加法溢出

    uchar num1 = 249;

    uchar num2 = 69;

    uchar sum = num1 + num2;

    那么sum等于多少呢?

    程序运行结果显示:249+69=62!!为什么会这样呢?明明249+69=318才对呀。

    因为318超出了uchar类型所能表示的极限,uchar只能表示[0, 255]。(255 = 2 ^ 8 - 1)。

    就像256个刻度的钟表无法表示318一样,那么最后318只能在绕了一圈超出0/256刻度以后,继续沿着顺时针走(318-256=62)步,最终停在62。

    【总结】无符号加法溢出的计算方法:溢出值 - 256。

    即(249 + 69) - 256 = 62。

    • 举个栗子:减法溢出

    uchar num1 = 69;

    uchar num2 = 72;

    uchar sum = num1 - num2;

    那么sum等于多少呢?

    69-72应当等于-3。但是同理,-3超出了[0, 255]。

    -3可以理解为从0/256刻度往逆时针走了3刻度,停在了253。

    【总结】无符号减法溢出的计算方法:溢出值+256。

    即(69 - 72 ) + 256 = 253。

    (0 - 255) + 256 = 1。

    • 举个栗子:减法溢出
    • 加法溢出

    【问】*如何判断一个机器是大端还是小端

    【答】使用指针法或联合体的特性来判断。

    具体代码见解析

    【解析】

    【考察点】大小端的概念以及16bit类型变量转换成8bit类型变量的原理

  • 基本概念
  • 对于位数大于8bit的处理器,由于寄存器宽度大于一个Byte,那么必然存在着一个如何将多个Byte安排的问题。

    因此就有了大端存储模式和小端存储模式

    • 具体表现

    若将0x12345678放入计算机中就有两种方法:

    1) 大端模式 Big Endian

    数据的高字节保存在内存的低地址低字节保存在内存的高地址

    大端更符合我们的书写习惯:先写高位数据,再写低位数据

    大端

    低地址  12  34  56  78  高地址

    —————————————————>   内存地址递增方向  

    2) 小端模式 Little Endian

    数据的高字节保存在内存高地址,低字节保存在内存的低地址

    小端

    低地址  78  56  34  12  高地址

     —————————————————>   内存地址递增方向

    • 判断方法

    指针法

    #include <stdio.h>
    
    int main(void)
    {
      char nChrNum;
      int nIntNum = 0x12345678;      
      int *pStartPos = &nIntNum; 	/*将nIntNum的起始地址赋值给指针pStartPos */
      nChrNum = *pStartPos;
    
      if (nChrNum == 0x78) 	/*nChrNum截取了nIntNum的低位*/
    	  printf("\nLittle Endian\n\n");
      else		 /*nChrNum截取了nIntNum的高位,即nChrNum == 0x00*/
    	  printf("\nBit Endian\n\n");
    }
    
    

    联合体法

    #include <stdio.h>
    
    /*2-联合体法*/
    int main(void)
    {
        union Union
        {
            int nIntNum;
            char nChrNum;
        }Union1;
    
        /*联合体union是一种具有多个类型或格式的值,在任何时候只有一个值*/
        Union1.nIntNum = 0x12345678;
    
        if (Union1.nChrNum == 0x78) 	/*联合体以char类型表示*/
            printf("\nLittle Endian\n\n");
        else		 /*联合体以int类型表示,即nChrNum == 0x00*/
            printf("\nBit Endian\n\n");
    }
    
    

    }

    • 原理解析

    首先我们要明确一个概念,所有的数据在计算机内部都是以“二进制”保存的。

    只不过在使用读取时,使用不同类型来翻译这一段二进制数据。

    否则我们为什么要强调数据的类型,必须先定义变量的类型才能使用。

    这是因为不这样做,计算机也不知道要将数据翻译成什么类型。

    由联合体union的特性可知:

    共用体表示几个变量共用一个内存位置,在不同的时间保存不同的数据类型和不同长度的变量。

    在union中,所有的共用体成员共用一个空间,并且同一时间只能储存其中一个成员变量的值。

    因此当我们使用int类型来存储0x12345678后,再使用char类型读取该数据时

    计算机会发现只能以8bit来翻译,也就是只能提供低8位的数据。

    指针法同理,从地址开始处只能读取8bit。

    • 羽你俗说

    通俗地说,我们无法将4升水(int,4Byte, 32bit)倒进一个1升(8bit)容量的瓶子里,因此只有最初的1升水(低8bit)可以倒进去保留,后续的3升水(高24bit)都溢出丢失了。

    更多内容,持续更新中!!!

    【觉得有用的小伙伴们可以订阅一下专栏,后续还有更多文章哦~ 😀 】

    作者其他专栏

    【嵌入式校招指南_完整学习路线】https://www.nowcoder.com/creation/manager/columnDetail/MWZkkj

    请帮忙点赞、评论+收藏,是对我最大的支持~感谢!!!

    全部评论
    【觉得有用的小伙伴们可以订阅一下专栏,后续还有更多文章哦~ 😀 】 请帮忙点赞、评论+收藏,是对我最大的支持~感谢!!!
    1 回复 分享
    发布于 2023-05-27 00:54 广东
    三连😏
    点赞 回复 分享
    发布于 2023-05-27 00:58 河南
    点赞 回复 分享
    发布于 2023-05-27 17:52 广东
    点赞 回复 分享
    发布于 2023-05-27 17:53 广东
    写的太好了!非常受用,感觉很多问题都分析的非常清楚。
    点赞 回复 分享
    发布于 2023-05-29 17:07 湖北
    你好,能问下以后从事嵌入式,考研选哪个方向
    点赞 回复 分享
    发布于 2023-05-30 13:32 江苏
    作者机械硕士,从零开始自学嵌入式软件,21届秋招进入国内芯片大厂。 从自身转行经历来看,网上嵌入式学习路线的资料少之又少,大多千篇一律且复制粘贴。 而嵌入式入行门槛高,技能树要求多,学习难度非常大,没有有效的方法指导,很容易迷失方向,错过校招。 在此专栏分享我的校招从零开始转行经验,听我给你娓娓道来~ https://www.nowcoder.com/creation/manager/columnDetail/MWZkkj😀
    点赞 回复 分享
    发布于 2023-05-30 15:59 广东

    相关推荐

    42 216 评论
    分享
    牛客网
    牛客企业服务