本篇为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;
}