嵌入式面试——C语言和数据结构篇(二)

本篇为C语言和数据结构篇(二)

1、关键字static的作用是什么?

答:

在C语言中,关键字static有三个明显的作用:

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

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

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

2、“引用”与指针的区别是什么?

答 :

1>引用必须被初始化,指针不必。

2>引用初始化以后不能被改变,指针可以改变所指的对象。

3>不存在指向空值的引用,但是存在指向空值的指针。

        指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使用指针,程序的可读性 差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。

3、.h头文件中的ifndef/define/endif 的作用?

答:

        防止该头文件被重复引用。

4、#include<file.h> 与 #include "file.h"的区别?

答:

        前者是从Standard Library的路径寻找和引用file.h,而后者是从当前工作路径搜寻并引用file.h。

5、描述实时系统的基本特性

答 :

        在特定时间内完成特定的任务,实时性与可靠性。

6、全局变量和局部变量在内存中是否有区别?如果有,是什么区别?

答 :

        全局变量储存在静态数据区,局部变量在堆栈中。

7、什么是平衡二叉树?

答 :

        左右子树都是平衡二叉树 且左右子树的深度差值的绝对值不大于1。

8、堆栈溢出一般是由什么原因导致的?

答 :

1>没有回收垃圾资源

2>层次太深的递归调用

9、局部变量能否和全局变量重名?

答:

        能,局部会屏蔽全局。要用全局变量,需要使用"::"

        局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。对于有些编译器而言,在同一个函数内可以定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内

10、如何引用一个已经定义过的全局变量?

答 :

        可以用引用头文件的方式,也可以用extern关键字,如果用引用头文件方式来引用某个在头文件中声明的全局变量,假定你将那个变量写错了,那么在编译期间会报错,如果你用 extern 方式引用时,假定你犯了同样的错误,那么在编译期间不会报错,而在连接期间报错。

11、全局变量可不可以定义在可被多个.C文件包含的头文件中?为什么?

答 :

        可以,在不同的C文件中以static形式来声明同名全局变量。

        可以在不同的C文件中声明同名的全局变量,前提是其中只能有一个C文件中对此变量赋初值,此时连接不会出错。

12、do……while 和 while……do 有什么区别?

答 :

        前一个循环一遍再判断,后一个判断以后再循环。

13、++i 和 i++有什么区别?

答:

        ++i 和 i++ 都是自增操作符,但它们的区别在于自增的时机和返回值。

        ++i(前缀递增): ++i 表示先将变量 i 的值加 1,然后再使用加 1 后的值。

int i = 5;

int result = ++i;

System.out.println(result); // 输出 6

        i++(后缀递增): i++ 表示先使用变量 i 的当前值,然后再将 i 的值加 1。

int i = 5;

int result = i++;

System.out.println(result); // 输出 5

        总的来说,++i 和 i++ 的区别在于自增操作的时机,即先递增还是先使用当前值。

14、什么是预编译,何时需要预编译?

答:

        预编译又称为预处理,是做些代码文本的替换工作。处理#开头的指令,比如拷贝#include包含的文件代码,#define宏定义的替换,条件编译等,就是为编译做的预备工作的阶段,主要处理#开始的预编译指令,预编译指令指示了在程序正式编译前就由编译器进行的操作,可以放在程序中的任何位置。

        c 编译系统在对程序进行通常的编译之前,先进行预处理。

        c提供的预处理功能主要有以下三种:

1>宏定义   

2>文件包含   

3>条件编译

        1、 总是使用不经常改动的大型代码体。 

        2、程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。在这种情况下,可以将所有包含文件预编译为一个预编译头。

15、Const 关键词

        以下关于 const 定义的代码分别是什么意思?

const int a;

int const a;

const int *a;

int * const a;

int const * a const;

答:

        第一、二的作用是一样,a是一个常整型数。

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

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

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

16、关键字volatile有什么含意?并给出三个不同的例子。

答:

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

        下面是volatile变量的几个例子:

1> 并行设备的硬件寄存器(如:状态寄存器)

2> 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)

3> 多线程应用中被几个任务共享的变量

17、有关volatile:

Q1:一个参数既可以是const还可以是volatile吗?解释为什么。

A1:可以。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。

Q2: 一个指针可以是volatile 吗?解释为什么。

A2:可以。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。

18、结构体与联合体有和区别?

答:

1>结构体和联合体都是由多个不同的数据类型成员组成, 但在任何同一时刻, 联合体中只存放了一个被选中的成员(所有成员共用一块地址空间), 而结构体的所有成员都存在(不同成员的存放地址不同)。 

2>对于联合体的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存在了, 而对于结构体的不同成员赋值是互不影响的。

19、论述含参数的宏与函数的优缺点

20、用两个栈实现一个队列的功能?要求给出算法和思路!

答 、

设2个栈为A,B,一开始均为空。

入队:

        将新元素push入栈A;

出队:

        (1)判断栈B是否为空;

        (2)如果不为空,则将栈A中所有元素依次pop出并push到栈B;

        (3)将栈B的栈顶元素pop出;

这样实现的队列入队和出队的平摊复杂度都还是O(1)。

21、嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢?

答:

while(1)
{


}

尽量不要使用

for(;;)
{


}

因为这样写的话,有可能面试官会让你解释一下这个语法以及为什么要这样写。

22、位操作(Bit manipulation) 

问:

        嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a,写两段代码,第一个设置a的bit 3,第二个清除a 的bit 3。在以上两个操作中,要保持其它位不变。

答:

        用 #defines 和 bit masks 操作。这是一个有极高可移植性的方法,解决方案如下:

#define BIT3 (0x1 << 3)

static int a;

void set_bit3(void) 

{

    a |= BIT3;

}

void clear_bit3(void) 

{

    a &= ~BIT3;

}

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值