参考答案只供参考!
第1题 找出程序中的错误
#define MAX_SRM 256
DSN get_SRM_no()
{
static int SRM_no;
int I;
for(I=0;I<MAX_SRM;I++)
{
SRM_no %= MAX_SRM;
if(MY_SRM.state==IDLE)
{
break;
}
}
if(I>=MAX_SRM)
return (NULL_SRM);
else
return SRM_no;
}
参考答案:
这应该是缺少了SRM_no的修改,可以在for循环中的循环变量修改语句I++后加入SRM_no++语句,如果只返回SRM_no就没有什么意义了。因为找了此题一些相关原题形式,说应该是嵌入式相关的程序,应该是查找空闲SRAM中空闲块编号。
第2题
int func(int a)
{
int b;
switch(a)
{
case 1: b=30;
case 2: b=20;
case 3: b=16;
default: b=0;
}
return b;
}
则func(1)=?
参考答案:
func(1)=0,因为当a=1时,与case 1匹配,但因为每个case之后都没有break语句,因此顺序执行case语句直到default语句执行之后才跳出switch语句块,此时b=0,所以相应的函数返回值也是0.
第3题
CObject类中的析构函数为什么虚析构函数?面试SE时,很多公司喜欢问到虚函数相关。MFC类库中,CObject类的重要性不言自明的。在CObject的定义中,我们看到一个有趣的现象,即CObject的析构函数是虚拟的。
参考答案:
虚析构函数用于动态分配类层次结构对象时,指引delete运算符选择正确的析构调用。
请注意构造函数是不能定义为虚的,因为在建立一个派生类对象时,必须从类层次的根开始,沿着继承路径逐个调用基类的构造函数,直至自身的构造函数,不能选择性地调用构造函数。所以定义虚构造函数没有意义,定义虚构造函数将产生语法错误。
第4题
什么是预编译?何时需要预编译?
参考答案:预编译又称为预处理,是做一些代码文本的替换工作。处理#开头的指令,例如拷贝#include包含的文件代码,#define宏定义的替换,条件编译等。就是为编译做的预备工作的阶段。主要处理#开始的预编译指令。预编译指令指示了在程序编译前就由编译器做的编译操作,可以放在程序中的任何位置。
何时需要预编译:
1.总是使用不经常改动的程序代码体。
2.程序由多个模块组成,所有模块都是用一组标准的包含文件和相同的编译选项。在这种情况下,可以将所有的包含文件预编译为一个预编译头。
第5题
char *const p;
char const *p;
const char *p;
请指出上述三个的区别?
参考答案:
char *const p是对定义一个const指针p,它与其它常量一样定义时候必须进行初始化,而且初始化之后它永远只指向初始化时它所指向的那个变量。
char const *p 和const char *p是指向const对象的指针的两种不同的形式,不同之处在于把const关键字放在了类型的后边或者前边,这种指向const对象的指针所指向的对象不一定非得是const对象,也可以是非const对象。指向const对象的指针可以用于函数的形参,这样可以防止在调用函数时对实际对象的修改。
这样综合const指针和指向const对象的指针就有了指向const对象的const指针,例如:const char *const p,这时不仅指针本身就是一个常量对象,它也可以指向const对象,也可以不指向const对象。
第6题
字符串拷贝函数strcpy的编写,用c语言实现。
参考答案:
以下代码是VC CRT(c运行时库)中的源码:
char *strcpy(char *dst, const char *src)
{
char *cp =dst;
while(*cp++ = *src++)
{
;
}
return (dst);
}
第7题
一个32位的机器的指针是多少位?
参考答案:指针是多少位的就看地址总线是多少位的,80386以后的数据总线的位数都是32位的,所以指针的位数也是32位的。
第8题
main()
{
int a[ 5 ] = { 1 , 2 , 3 , 4 , 5 };
int * ptr = ( int * )( & a + 1 );
printf( " %d,%d " , * (a + 1 ), * (ptr - 1 ));
}
答:2,5
*(a+1)就是a[1],*(ptr-1)就是a[4], 执行结果是2, 5。&a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int)。int *ptr=(int *)(&a+1); 则ptr实际是&(a[5]),也就是a+5
原因如下:
&a是数组指针,其类型为 int (*)[5]; 而指针加1要根据指针类型加上一定的值,不同类型的指针+1之后增加的大小不同; a是长度为5的int数组指针,所以要加 5*sizeof(int)。所以ptr实际是a[5]。但是prt与(&a+1)类型是不一样的(这点很重要),所以prt-1只会减去sizeof(int*)。a,&a的地址是一样的,但意思不一样,a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5]。
第9题 以下代码有什么问题?
int main()
{
char a;
char * str =& a;
strcpy(str, " hello " );
printf(str);
return 0 ;
}
答:没有为str分配内存空间,将会发生异常。问题出在将一个字符串复制进一个字符变量指针所指地址。虽然可以正确输出结果,但因为越界进行内在读写而导致程序崩溃。
第10题
写一个“标准”宏,使在这个宏中输入两个参数,返回较小的一个。
参考答案:
#define MIN(X,Y) ((X)>(Y)?(Y):(X))
请注意在宏的结尾是没有分号";"的。
第11题
关键字violate的含义?并说出三个使用violate的场合.
参考答案:
violate关键字修饰的变量可能会被意想不到的改变,精确地说是,优化器在每次使用这个violate修饰的变量时候,都会从内存中读取,而不使用保存在寄存器里的备份。
使用violate的变量的例子:
1.在多线程的程序中多个线程同时访问的同一个变量即共享变量前面应该加上violate.
2.一个中断服务子程序中会访问到的非自动变量。
3.并行设备的硬件寄存器(例如,状态寄存器)。