文档库 最新最全的文档下载
当前位置:文档库 › C-C++mst01

C-C++mst01

C-C++mst01
C-C++mst01

一、static有什么用途?(请至少说明两种)

答:1.限制变量的作用域 2.设置变量的存储域

二、C++中引用和指针的区别:

答:1 、要认识到在任何情况下都不能使用指向空值的引用。一个引用必须总是指向某些对象,因为引用肯定会指向一个对象,在C++里,引用应被初始化。指针没有这样的限制,不存在指向空值的引用这个事实意味着使用引用的代码效率比使用指针的要高。因为在使用引用之前不需要测试它的合法性。

例如:void printDouble(const double& rd)

{

cout << rd; // 不需要测试rd,它肯定指向一个double值

}

相反,指针则应该总是被测试,防止其为空:

void printDouble(const double *pd)

{

if (pd)

{ // 检查是否为NULL

cout << *pd;

}

}

2 、指针与引用的另一个重要的不同是指针可以被重新赋值以指向另一个不同的对象,引用则总是指向在初始化时被指定的对象,以后不能改变。

string s1="John";

string s2="Billy";

string &rs=s1;//rs引用s1

string *ps=s1;//ps指向s1

rs=s2;//rs仍引用s1,但此时s1的值为"Billy"

ps=s2;//ps指向s2,但s1此时的值没有发生改变

3、引用只是个变量的别名不占用存储空间

指针是个变量占用存储空间

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

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

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

答:全局变量储存在静态数据区,局部变量在堆栈中。(预备知识—程序的内存分配一个由C/C++编译的程序占用的内存分为以下几个部分1、栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。2、堆区(heap)—由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。3、全局区(静态区)(static)—全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。4、文字常量区—常量字符串就是放在这里的,程序结束后由系统释放。5、程序代码区—存放函数体的二进制代码。)

五、什么是平衡二叉树?(查看数据结构)

答:左右子树都是平衡二叉树,且左右子树的深度差值的绝对值不大于1。(完全二叉树必然是平衡二叉树)

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

答:没有回收垃圾资源(堆栈中的物体具有一个特性: 最后一个放入堆栈中的物体总是被最先拿出来)

七、什么函数不能声明为虚函数?

答:constructor--构造函数((1)非类的成员函数不能定义为虚函数,类的成员函数中静态成员函数和构造函数也不能定义为虚函数,但可以将析构函数定义为虚函数。实际上,优秀的程序员常常把基类的析构函数定义为虚函数。因为,将基类的析构函数定义为虚函数后,当利用delete删除一个指向派生类定义的对象指针时,系统会调用相应的类的析构函数。而不将析构函数定义为虚函数时,只调用基类的析构函数。(2)只需要在声明函数的类体中使用关键字“virtual”将函数声明为虚函数,而定义函数时不需要使用关键字“virtual”。(3)当将基类中的某一成员函数声明为虚函数后,派生类中的同名函数自动成为虚函数。(4)如果声明了某个成员函数为虚函数,则在该类中不能出现和这个成员函数同名并且返回值、参数个数、类型都相同的非虚函数。在以该类为基类的派生类中,也不能出现这种同名函数。虚函数联系到多态,多态联系到继承。所以本文中都是在继承层次上做文章。没了继承,什么都没得谈)

八、冒泡排序算法的时间复杂度是什么?

答:O(n^2)

九、写出float x 与“零值”比较的if语句。

答:if(x>0.000001&&x<-0.000001)

十、Internet采用哪种网络协议?该协议的主要层次结构?

答:tcp/ip (一般来说:TCP提供运输层服务,而IP提供网络层服务)

应用层/传输层/网络层/数据链路层/物理层

十一、Internet物理地址和IP地址转换采用什么协议?

答:ARP (Address Resolution Protocol)(地址解析协议)

十二、IP地址的编码分为哪俩部分?

答:IP地址由两部分组成,网络号和主机号。不过是要和“子网掩码”按位与上之后才能区分哪些是网络位哪些是主机位。(IP的结构和分类:在IP地址的这四部分中,又可以分成两部分,一部分是网络号Network(用来标识网络),一部分是主机号(标识在某个网络上的一台特定的主机)。大家可能会问,那在这四部分中,哪部分表示网络,哪部分表示主机呢?因此在这,我们把IP地址分成A,B,C类。A类地址,第一组表示网络,后面三组表示主机。B 类地址,第一,二组表示网络,后面两组表示主机。C类地址,第一,二,三组表示网络,最后一组表示主机。)十三、用户输入M,N值,从1至N开始顺序循环数数,每数到M输出该数值,直至全部输出。写出C程序。

答:循环链表,用取余操作做

十四、不能做switch()的参数类型是:

答:switch的参数不能为实型。

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

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

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

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

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

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

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

十八、语句for( ;1 ;)有什么问题?它是什么意思?

答:和while(1)相同。

十九、do……while和while……do有什么区别?

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

二十、请写出下列代码的输出内容

#include

main()

{

int a,b,c,d;

a=10;

b=a++; //先取值,再加1

c=++a; //先加1,再取值

d=10*a++;//先取值乘以10赋给d,a再加1

printf("b,c,d:%d,%d,%d",b,c,d);

return 0;

}

答:10,12,120

二十一、static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?

答:全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。

从以上分析可以看出,把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量

改变为静态变量后是改变了它的作用域,限制了它的使用范围。

static函数与普通函数作用域不同。仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件

static全局变量与普通的全局变量有什么区别:static全局变量只初使化一次,防止在其他文件单元中被引用;

static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依据上一次结果值;

static函数与普通函数有什么区别:static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝。

程序的局部变量存在于(堆栈)中,全局变量存在于(静态区)中,动态申请数据存在于(堆)中。

二十二、设有以下说明和定义:

typedef union {long i; int k[5]; char c;} DATE;

struct data { int cat; DATE cow; double dog;} too;

DA TE max;

则语句printf("%d",sizeof(struct date)+sizeof(max));的执行结果是:___52____

答:DATE是一个union(联合体)变量公用空间.里面最大的变量类型是int[5], 占用20个字节. 所以它的大小是20

data是一个struct, 每个变量分开占用空间. 依次为int4 + DATE20 + double8 = 32.

所以结果是20 + 32 = 52.

当然...在某些16位编辑器下, int可能是2字节,那么结果是int2 + DATE10 + double8 = 20

二十三、队列和栈有什么区别?

答:队列先进先出,栈后进先出

二十四、写出下列代码的输出内容(看不明白)

#include

int inc(int a)

{

return(++a);

}

int multi(int*a,int*b,int*c)

{

return(*c=*a**b);

}

typedef int(FUNC1) (int in);

typedef int(FUNC2) (int*,int*,int*);

void show(FUNC2 fun,int arg1, int *arg2)

{

INC p=&inc;

int temp =p(arg1);

fun(&temp,&arg1, arg2);

printf("%d\n",*arg2);

}

main()

{

int a;

show(multi,10,&a);

return 0;

}

答:110

二十五、请找出下面代码中的所有错误

说明:以下代码是把一个字符串倒序,如“abcd”倒序后变为“dcba”

1、#include"string.h"

2、main()

3、{

4、char*src="hello,world";

5、char* dest=NULL;

6、int len=strlen(src);

7、dest=(char*)malloc(len);

8、char* d=dest;

9、char* s=src[len];

10、while(len--!=0)

11、d++=s--;

12、printf("%s",dest);

13、return 0;

14、}

答:方法1:

int main()

{ char* src = "hello,world";

int len = strlen(src);

char* dest = (char*)malloc(len+1);//要为\0分配一个空间

char* d = dest;

char* s = &src[len-1];//指向最后一个字符

while( len-- != 0 )

*d++=*s--;

*d = 0;//尾部要加\0

printf("%s\n",dest);

free(dest);// 使用完,应当释放空间,以免造成内存汇泄露

return 0;

}

方法2://二分法

#include

#include

main()

{

char str[]="hello,world";

int len=strlen(str);

char t;

for(int i=0; i

{

t=str[i];

str[i]=str[len-i-1];

str[len-i-1]=t;

}

printf("%s",str);

return 0;

}

二十六、-1,2,7,28,,126请问28和126中间那个数是什么?为什么?

答:答案应该是4^3-1=63

规律是n^3-1(当n为偶数0,2,4)

n^3+1(当n为奇数1,3,5)

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

答:设2个栈为A,B, 一开始均为空.

入队: 将新元素push入栈A;

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

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

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

这样实现的队列入队和出队的平摊复杂度都还是O(1), 比上面的几种方法要好。

二十八、在C语言库函数中将一个字符转换成整型的函数是atool()吗,这个函数的原型是什么?

答:函数名: atol

功能: 把字符串转换成长整型数

用法: long atol(const char *nptr);

程序例:

#include

#include

int main(void)

{

long l;

char *str = "98765432";

l = atol(lstr);

printf("string = %s integer = %ld\n", str, l);

return(0);

}

二十九、对于一个频繁使用的短小函数,在C语言中应用什么实现,在C++中应用什么实现?

答:c用宏定义,c++用inline(inline 定义的类的内联函数,是向编译器发出的一个请求,而不是一个命令)三十、直接链接两个信令点的一组链路称作什么?

答:PPP点到点连接(点对点协议(PPP)为在点对点连接上传输多协议数据包提供了一个标准方法。PPP 最初设计是为两个对等节点之间的 IP 流量传输提供一种封装协议。在 TCP-IP 协议集中它是一种用来同步调制连接的数据链路层协议(OSI 模式中的第二层),替代了原来非标准的第二层协议,即 SLIP。除了 IP 以外 PPP 还可以携带其它协议,包括 DECnet 和 Novell 的 Internet 网包交换(IPX)。)三十一、软件测试都有那些种类?

答:黑盒:针对系统功能的测试白合:测试函数功能,各函数接口

三十三、进程和线程的差别。

答:线程是指进程内的一个执行单元,也是进程内的可调度实体.

与进程的区别: (1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位

(2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行

(3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源.

(4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。

三十四、.测试方法

答:人工测试:个人复查、抽查和会审

机器测试:黑盒测试和白盒测试

三十五、Heap与stack的差别。

答:Heap是堆,stack是栈。

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

Stack空间有限,Heap是很大的自由存储区,C中的malloc函数分配的内存空间即在堆上,C++中对应的是new操作符。程序在编译期对变量和函数分配内存都在栈上进行,且程序运行过程中函数调用时参数的传递也在栈上进行三十六、网络编程中设计并发服务器,使用多进程与多线程,请问有什么区别?

答:1,进程:子进程是父进程的复制品。子进程获得父进程数据空间、堆和栈的复制品。

2,线程:相对与进程而言,线程是一个更加接近与执行体的概念,它可以与同进程的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。

两者都可以提高程序的并发度,提高程序运行效率和响应时间。

线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源管理和保护;而进程正相反。同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移。

三十七、用宏定义写出swap(x,y)

答:#define swap(x, y)\x = x + y;\ y = x - y;\ x = x - y;

三十八、一语句实现x是否为2的若干次幂的判断

答:int i = 512;

cout << boolalpha << ((i & (i - 1)) ? false : true) << endl;

三十九、unsigned int intvert(unsigned int x,int p,int n)实现对x的进行转换,p为起始转化位,n为需要转换的长度,假设起始点在右边.如x=0b0001 0001,p=4,n=3转换后x=0b0110 0001

答:unsigned int intvert(unsigned int x,int p,int n)

{ unsigned int _t = 0;

unsigned int _a = 1;

for(int i = 0; i < n; ++i)

{

_t = _a;

_a = _a << 1;

}

_t = _t << p;

x ^= _t;

return x;

}

四十、char * const p; char const * p; const char *p

上述三个有什么区别?

答:char * const p; //常量指针,p的值不可以修改

char const * p;//指向常量的指针,指向的常量值不可以改

const char *p;//和char const *p

四十一、以下代码中的两个sizeof用法有问题吗?[C易]

void UpperCase( char str[] ) // 将str 中的小写字母转换成大写字母

{

for( size_t i=0; i

if( 'a'<=str[i] && str[i]<='z' )

str[i] -= ('a'-'A' );

}

char str[] = "aBcDe";

cout << "str字符长度为: " << sizeof(str)/sizeof(str[0]) << endl;

UpperCase( str );

cout << str << endl;

答:函数内的sizeof有问题。根据语法,sizeof如用于数组,只能测出静态数组的大小,无法检测动态分配的或外部数组大小。函数外的str是一个静态定义的数组,因此其大小为6,函数内的str实际只是一个指向字符串的指针,没有任何额外的与数组相关的信息,因此sizeof作用于上只将其当指针看,一个指针为4个字节,因此返回4。一个32位的机器,该机器的指针是多少位指针是多少位只要看地址总线的位数就行了。80386以后的机子都是32的数据总线。所以指针的位数就是4个字节了。

四十二、以下程序输出结果是什么?

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].

四十三、请问以下代码有什么问题:

int main()

{

char a;

char *str=&a;

strcpy(str,"hello");

printf(str);

return 0;

}

答:没有为str分配内存空间,将会发生异常,问题出在将一个字符串复制进一个字符变量指针所指地址。虽然可以正确输出结果,但因为越界进行内在读写而导致程序崩溃。

四十四、以下程序有什么错?

char* s="AAA";

printf("%s",s);

s[0]='B';

printf("%s",s);

答:"AAA"是字符串常量。s是指针,指向这个字符串常量,所以声明s的时候就有问题。

cosnt char* s="AAA"; 然后又因为是常量,所以对是s[0]的赋值操作是不合法的。

四十五、int(*s[10])(int)表示的是什么?

答:int(*s[10])(int)函数指针数组,每个指针指向一个int func(int param)的函数。

char (*str)[20]; //str是一个数组指针,即指向数组的指针

char *str[20]; //str是一个指针数组,其元素为指针型数据

四十六、写一个“标准”宏,这个宏输入两个参数并返回较小的一个。

答:.#define Min(X, Y) ((X)>(Y)?(Y):(X)) //结尾没有;

四十七、嵌入式系统中经常要用到无限循环,你怎么用C编写死循环。

答:while(1){}或者for(;;)

四十八、关键字const有什么含意?

答:表示常量不可以修改的变量,const意味着"只读"。

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

const int a;

int const a;

const int *a;

int * const a;

int const * a const;

前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。如果应试者能正确回答这些问题,那么他就给我留下了一个好印象。顺带提一句,也许你可能会问,即使不用关键字const,也还是能很容易写出功能正确的程序,那么我为什么还要如此看重关键字const呢?我也如下的几下理由:

1) 关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清理的。)

2) 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。

3) 合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。)

四十九、关键字volatile有什么含意?并举出三个不同的例子?

答:提示编译器对象的值可能在编译器未监测到的情况下改变。

一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:

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

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

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

回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。搞嵌入式的家伙们经常同硬件、中断、RTOS等等打交道,所有这些都要求用到volatile变量。

1). 一个参数既可以是const还可以是volatile吗?解释为什么。

2). 一个指针可以是volatile 吗?解释为什么。

3). 下面的函数有什么错误:

int square(volatile int *ptr)

{

return *ptr * *ptr;

}

下面是答案:

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

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

3). 这段代码的有个恶作剧。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:

int square(volatile int *ptr)

{

int a,b;

a = *ptr;

b = *ptr;

return a * b;

}

由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:

long square(volatile int *ptr)

{

int a;

a = *ptr;

return a * a;

}

V olatile 关键字告诉编译器不要持有变量的临时性拷贝。一般用在多线程程序中,以避免在其中一个线程操作该变量时,将其拷贝入寄存器。请看以下情形:

A线程将变量复制入寄存器,然后进入循环,反复检测寄存器的值是否满足一定条件(它期待B线程改变变量的值)。在此种情况下,当B线程改变了变量的值时,已改变的值对其在寄存器的值没有影响。所以A线程进入死循环。volatile 就是在此种情况下使用。

五十、有以下表达式:

int a=248; b=4;

int const c=21;

const int *d=&a;

int *const e=&b;

int const *f const =&a;

请问下列表达式哪些会被编译器禁止?为什么?

答:*c=32; d=&b; *d=43; e=34; e=&a; f=0x321f;

*c 这是个什么东东,禁止

*d 说了是const,禁止

e = &a 说了是const 禁止

const *f const =&a; 禁止

五十一、.交换两个变量的值,不使用第三个变量。即a=3,b=5,交换之后a=5,b=3;

答:有两种解法, 一种用算术算法, 一种用^(异或)

a = a + b;

b = a - b;

a = a - b;

或者

a = a^b; // 只能对int, char..

b = a^b;

a = a^b;

或者

a ^=

b ^= a;

五十二、c和c++中的struct有什么不同?

答:c和c++中struct的主要区别是c中的struct不可以含有成员函数,而c++中的struct可以。c++中struct和class的主要区别在于默认的存取权限不同,struct默认为public,而class默认为private

五十三、char szstr[10];

strcpy(szstr,"0123456789");

产生什么结果?为什么?

答:长度不一样,会造成非法的OS

五十四、(void *)ptr 和(*(void**))ptr的结果是否相同?其中ptr为同一个指针

答:(void *)ptr 和(*(void**))ptr值是相同的

五十五、int main()

{

int x=3;

printf("%d",x);

return 1;

}

问函数既然不会被其它函数调用,为什么要返回1?

答:main中,c标准认为0表示成功,非0表示错误。具体的值是某中具体出错信息

五十六、要对绝对地址0x100000赋值,我们可以用(unsigned int*)0x100000 = 1234; 那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做?

答:*((void (*)( ))0x100000 ) ( );

首先要将0x100000强制转换成函数指针,即: (void (*)())0x100000

然后再调用它: *((void (*)())0x100000)();

用typedef可以看得更直观些: typedef void(*)() voidFuncPtr; *((voidFuncPtr)0x100000)();

五十七、已知一个数组table,用一个宏定义,求出数据的元素个数#define NTBL

答:#define NTBL (sizeof(table)/sizeof(table[0]))

相关文档