嵌入式软件面试题整理(一)

1.用#define声明一个常数,表明1年中有多少秒(忽略闰年问题)?

//答
#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL

        要点:

        A.没有以分号结束;

        B.懂得预处理器将为你计算常数表达式的值。即60 * 60 * 24 * 365而不是31536000.

        C.考虑到了16位机将会溢出,巧妙运用了UL。

                UL表示unsigned long无符号长整数,例如100UL表示这是一个无符号长整数。

              (UL详情:C语言宏定义后面的U、L、UL_c语言 ull-CSDN博客

2.写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个?

//答
#define MIN(A,B) ((A) <= (B) ? (A) : (B))

        要点:

        A.参数用括号括起来;

        B.考察能否合理运用条件运算符;

3.Heap与Stack的差别?

        答案:Heap是堆,Stack是栈。

        Stack的空间由系统自动分配/释放,Heap上的空间手动分配/释放。

        Stack空间有限,Heap是很大的自由存储区,malloc函数分配的内存空间即在堆上。

//经典例子
int a = 0; //全局初始化区 
char *p1;//全局未初始化区 
void main(void)
{  
    int b;                     //栈   
    char s[] = "abc";          //栈   
    char *p2;                  //栈   
    char *p3 = "123456";       //123456\0在常量区,p3在栈上  
    static int c =0;           //全局(静态)初始化区   
    p1 = (char *)malloc(10);   //堆  
    p2 = (char *)malloc(20);   //堆 
}

4.用变量a给出下面的定义

A.一个整型数?

        答案:int a;

B.一个指向整型数的指针?

        答案:int *a;

C.一个指向指针的的指针,它指向的指针是指向一个整型数?

        答案:int **a;

D.一个有10个整型数的数组?

        答案:int a[10];

E.一个有10个指针的数组,该指针是指向一个整型数的?

        答案:int *a[10];

F.一个指向有10个整型数数组的指针?

        答案:int (*a)[10];

G.一个指向函数的指针,该函数有一个整型参数并返回一个整型数?

        答案:int (*a)(int);

H.一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数?

        答案:int (*a[10])(int);

5.关键字static的作用是什么?

        A.在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变;

        B.在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的局变量;

        C.在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用;

6.关键字const有什么含意?

        答案:const意味着"只读"。

        如果回答"const意味着常数",面试官会觉得你只是一个业余的人。

7.下面的声明都是什么意思?

const int a;
int const a;
const int *a;
int * const a;
int const * a const;

        A.前两个的作用是一样,a是一个常整型数;

        B.第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以);

        C.第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的);

        D.最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数 是不可修改的,同时指针也是不可修改的)。

7.1 const int* p (int const *p)和int *const p的区别

#include <stdio.h>
void test1()
{
    int n = 10;
    int m = 10;
    /* const放在*左边,修饰的是*p,表示的是指针指向的内容,不能通过指针来改变,
    但是指针变量本身是可以被修改的 */
    const int* p = &n;//const放在*的左边
    *p = 20;//err   *p不可改变(指针指向的内容不能被修改)
    p = &m; //ok    指针变量p可以修改
}
void test1()
{
    int n = 10;
    int m = 10;
    /* const放在*右边,修饰的是指针变量p本身,表示的是指针变量不可以被修改,
    但是指针指向的内容是可以被修改的 */
    int* const p = &n;//const放在*的右边
    *p = 20;//ok     //指针指向的内容可以被修改
    p = &m; //err    p不可改变(指针变量p不能被修改)
}
int main()
{
    test1();//const放在*的右边
    test2();//const放在*的左边
    return 0;
}

 总结:

①const int* p (int const *p):const放在*的左边。修饰的是*p,*p(指针指向的内容)不能修改p(指针变量本身)可以修改

②int * const p :const放在*的右边修饰的是pp(指针变量本身)不可以修改;*p(指针指向的内容)可以修改。

③int const * const p (const int * const p):*的左右两边都有const,修饰的是*p和p,所以*p和p都不能被修改

8.关键字volatile有什么含意?

        答案:一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。

        精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。

9.sizeof和strlen的区别?

        答案:sizeof是运算符,在编译时即计算好了;

                   而strlen是函数,要在运行时才能计算。

10.在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务?

//答
int *p;
p = (int*)0x67a9;        //将 0x67a9 转换为 int 类型的指针。
*p = 0xaa66;            /*通过指针 p 解引用并将地址 0x67a9 处的值设置为 0xaa66。
                        这里 0xaa66 被赋值给 int 类型变量,但注意 0xaa66 是一个 
                        short 类型的值(2字节),通常 int 类型的值(4字节)会以
                        未定义的方式填充其余字节。*/

11.给定一个整型变量a,写两段代码,第一个设置a的bit 3,第二个清除a 的bit 3。在以上两个操作中,要保持其它位不变?

#define BIT3 (0x1 << 3)
static int a;
void set_bit3(void)
{  
    a |= BIT3;       /*按位或操作,将 BIT3 的值(00001000)与 a 的当前值进行按位或
                            运算,这会将 a 的第3位置为1,而不改变其他位的值。*/
}
void clear_bit3(void)
{  
    a &= ~BIT3;      /*按位与操作,首先对 BIT3 进行取反操作(即 ~BIT3 变为 11110111)
                       然后与 a 进行按位与运算,这会将 a 的第3位清除为0,
                       而不改变其他位的值。*/
}

12.下面函数错误吗?

int square(volatile int *ptr)
{  
    return *ptr * *ptr;
}

错误——重复解引用return *ptr * *ptr; 会将 *ptr 解引用两次,这可能导致两次不同的值,因为 *ptr 的值可能在两次解引用之间发生变化。由于 ptr 是 volatile 类型,这意味着 *ptr 的值可能在程序运行时由外部因素改变,导致计算结果不一致。

修正建议:为了确保 *ptr 的值在计算过程中保持一致,可以将其存储在一个局部变量中:

int square(volatile int *ptr)
{
    int value = *ptr;  // 读取并存储值
    return value * value;  // 使用存储的值进行计算
}

很高兴您提到了2023年华为本科应届生嵌入式面试题。虽然我无法预测具体的面试题目,但我可以给您提供一些可能涉及的主题和问题,以供参考: 1. 嵌入式系统基础知识: - 解释嵌入式系统的概念和特点。 - 了解常见的嵌入式处理器架构和微控制器。 - 解释中断、中断向量表和中断处理程序的概念。 - 讨论实时操作系统(RTOS)的作用和常见特性。 2. 嵌入式软件开发: - 了解C/C++语言在嵌入式开发中的应用。 - 解释嵌入式系统的启动过程和初始化流程。 - 掌握裸机编程和驱动程序开发的基本原理。 - 熟悉嵌入式系统的调试和测试方法。 3. 嵌入式硬件设计: - 了解数字电路和模拟电路的基本知识。 - 掌握常见的总线协议(如I2C、SPI、UART)和接口标准(如GPIO)。 - 理解嵌入式系统的时钟和定时器设计。 - 熟悉硬件调试工具和仪器的使用。 4. 嵌入式系统应用: - 探讨嵌入式系统在物联网、智能家居、汽车电子等领域的应用。 - 分析嵌入式系统在电源管理、通信、图像处理等方面的解决方案。 - 讨论嵌入式系统的功耗优化和性能调优方法。 以上只是一些可能的面试主题和问题,具体的面试内容可能因岗位要求和面试官的选择而有所不同。我建议您在准备面试时,深入学习嵌入式系统的相关知识,并结合实际项目经验进行练习和复习。祝您面试顺利!如有更多问题,我随时为您解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值