为什么ios8数组越界崩溃程序崩溃,而访问回收了的内

查看:4818|回复:8
java虚拟机有垃圾回收机制,那么为什么还会出现内存溢出,什么时候出现内存溢出?
本帖最后由 redhat9i 于
13:08 编辑
主要的是这样的。。举个例子 当你堆里某个对象没有被引用时,,然后再过一段时间&&垃圾回收机制才会回收,,,那么
while(true){
String str=new String(&ni hao ni hao &);
一直循环创建 String对象。。。你觉得堆不会溢出嘛。。。
垃圾回收 要有2个条件
1 该对象没有被引用
2 过了一段时间
不知道有没说错。。求指导
天天好心情~~~
引用:原帖由 java_along 于
10:38 发表
主要的是这样的。。举个例子 当你堆里某个对象没有被引用时,,然后再过一段时间&&垃圾回收机制才会回收,,,那么
while(true){
String str=new String(&ni hao ni hao &);
一直循环创建 String对象。。。你觉得堆不会溢出嘛 ... 不知道我这例子举的对不对。。反正大概就是这意思。。我这例子好像有点问题。。。
天天好心情~~~
引用:原帖由 java_along 于
10:41 发表
不知道我这例子举的对不对。。反正大概就是这意思。。我这例子好像有点问题。。。 恩恩 我觉得好像对着,不知道有没有大神指导一下
。。。指导什么。。。
天天好心情~~~
是会回收 但是要你没用才会回收啊 如果虚拟机认为程序还有可能引用到的东西 是不会去主动回收的 所以很多时候写程序也要注意的 不是有回收机制就不用关心这个了
这个好像数组越界也是会造成的,不只是来不急回收,貌似,因为系统给他的大小比如是100,而你确取了101,系统满足不了你的要求,这就出显了内存溢出
虚拟机规范并没有规定什么时候,多久运行一次gc,不同的虚拟机提供商有不同的gc机制,但是gc只能回收不能到达的对象,也就是当你创建的对象没有指针指向了的时候,才可以被回收,如果你创建的活对象超过了内存的上限,那么gc帮不了任何忙。如何处理数组越界而不会让程序崩溃_百度知道
如何处理数组越界而不会让程序崩溃
我有更好的答案
问者的意思是出现错误,而不处理:try一下,catch里不要throw就可以了;或者try的时候,直接pass也行
专注培养IT技术人才
主营:PHP培训,JAVA培训,HTML5培训,UI培训,Linux培训,Python培训
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。2014年10月 C/C++大版内专家分月排行榜第三2014年4月 C/C++大版内专家分月排行榜第三
2013年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第七
2013年12月 C/C++大版内专家分月排行榜第二2013年12月 Linux/Unix社区大版内专家分月排行榜第二2013年11月 C/C++大版内专家分月排行榜第二2013年10月 C/C++大版内专家分月排行榜第二
2015年9月 VC/MFC大版内专家分月排行榜第二2015年7月 硬件/嵌入开发大版内专家分月排行榜第二2014年5月 VC/MFC大版内专家分月排行榜第二2014年3月 VC/MFC大版内专家分月排行榜第二2013年10月 VB大版内专家分月排行榜第二2013年7月 VB大版内专家分月排行榜第二2012年5月 VB大版内专家分月排行榜第二2012年4月 VB大版内专家分月排行榜第二2012年2月 VB大版内专家分月排行榜第二2011年11月 VB大版内专家分月排行榜第二
2015年11月 VC/MFC大版内专家分月排行榜第三2015年6月 VC/MFC大版内专家分月排行榜第三2015年2月 VC/MFC大版内专家分月排行榜第三2014年1月 VC/MFC大版内专家分月排行榜第三2012年3月 VB大版内专家分月排行榜第三2011年12月 VB大版内专家分月排行榜第三2011年10月 VB大版内专家分月排行榜第三
匿名用户不能发表回复!|C语言面试题大汇总(原版)_甜梦文库
C语言面试题大汇总(原版)
C 语言面试题大汇总 发布之前先申明两点: 1 所有资料来自网络(主要是 CSDN),本人只是收集和转发。 2 所有问题解答(尤其是代码)只是参考,不保证正确。先发基本问题,再发编程问题.......... 4. static 有什么用途?(请至少说明两种) 1.限制变量的作用域 2.设置变量的存储域 My: 3.限制函数作用域 7. 引用与指针有什么区别? 1) 引用必须被初始化,指针不必。 2) 引用初始化以后不能被改变,指针可以改变所指的对象。 2) 不存在指向空值的引用,但是存在指向空值的指针。 8. 描述实时系统的基本特性 在特定时间内完成特定的任务,实时性与可靠性 9. 全局变量和局部变量在内存中是否有区别?如果有,是什么区别? 全局变量储存在静态数据库,局部变量在堆栈 10. 什么是平衡二叉树? 左右子树都是平衡二叉树 且左右子树的深度差值的绝对值不大于 1 11. 堆栈溢出一般是由什么原因导致的? 没有回收垃圾资源 12. 什么函数不能声明为虚函数? constructor 13. 冒泡排序算法的时间复杂度是什么? O(n^2) 14. 写出 float x 与“零值”比较的 if 语句。 if(x&0.000001&&x&-0.. Internet 采用哪种网络协议?该协议的主要层次结构? tcp/ip 应用层/传输层/网络层/数据链路层/物理层 17. Internet 物理地址和 IP 地址转换采用什么协议? ARP (Address Resolution Protocol)(地址解析fh) 18.IP 地址的编码分为哪俩部分? IP 地址由两部分组成,网络号和主机号。不过是要和“子网掩码”按位与上之后才能区分哪些 是网络位哪些是主机位。 2.用户输入 M,N 值,从 1 至 N 开始顺序循环数数,每数到 M 输出该数值,直至全部输出。 写出 C 程序。 循环链表,用取余操作做 myadd:(最开始指向链表尾-&M) 3.不能做 switch()的参数类型是: switch 的参数不能为实型。 A 1、局部变量能否和全局变量重名? 答:能,局部会屏蔽全局。要用全局变量,需要使用&::& 局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会 用到全局变量。对于有些编译器而言,在同一个函数内可以定义多个同名的局部变量,比如 在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内 2、如何引用一个已经定义过的全局变量? 答:extern 可以用引用头文件的方式,也可以用 extern 关键字,如果用引用头文件方式来引用某个在头 文件中声明的全局变理,假定你将那个变写错了,那么在编译期间会报错,如果你用 extern 方式引用时,假定你犯了同样的错误,那么在编译期间不会报错,而在连接期间报错 3、全局变量可不可以定义在可被多个.C 文件包含的头文件中?为什么? 答:可以,在不同的 C 文件中以 static 形式来声明同名全局变量。 可以在不同的 C 文件中声明同名的全局变量,前提是其中只能有一个 C 文件中对此变量赋 初值,此时连接不会出错 4、语句 for( ;1 ;)有什么问题?它是什么意思? 答:和 while(1)相同。 5、do……while 和 while……do 有什么区别? 答:前一个循环一遍再判断,后一个判断以后再循环 6、请写出下列代码的输出内容 #include&stdio.h& main() { int a,b,c,d; a=10; b=a++; c=++a; d=10*a++; printf(&b,c,d:%d,%d,%d&,b,c,d); return 0; } 答:10,12,120 1、static 全局变量与普通的全局变量有什么区别?static 局部变量和普通局部变量有什么区 别?static 函数与普通函数有什么区别? 全 局变量(外部变量)的说明之前再冠以 static 就构成了静态的全局变量。全局变量本身就是 静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这 两者的区别虽在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组 成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用 域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于 静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用, 因此可以避 免在其它源文件中引起错误。 从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的 生存期。把全局变量改变为静态变量后是改变了它的作用域, 限制了它的使用范围。 static 函数与普通函数作用域不同。仅在本文件。只在当前源文件中使用的函数应该说明为 内部函数(static),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用 的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件 static 全局变量与普通的全局变量有什么区别:static 全局变量只初使化一次,防止在其他文 件单元中被引用; static 局部变量和普通局部变量有什么区别:static 局部变量只被初始化一次,下一次依据上 一次结果值; static 函数与普通函数有什么区别:static 函数在内存中只有一份,普通函数在每个被调用中 维持一份拷贝 2、程序的局部变量存在于(堆栈)中,全局变量存在于(静态区 )中,动态申请数据存在 于( 堆)中。 3、设有以下说明和定义: typedef union { int k[5];} DATE; struct data { DATE} DATE 则语句 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 4、队列和栈有什么区别? 队列先进先出,栈后进先出 5、写出下列代码的输出内容 #include&stdio.h& 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) { INCp=& int temp =p(arg1); fun(&temp,&arg1, arg2); printf(&%d\n&,*arg2); } main() { show(multi,10,&a); return 0; } 答:110 7、请找出下面代码中的所以错误 说明:以下代码是把一个字符串倒序,如“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= 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 = char* s = &src[len-1];//指向最后一个字符 while( len-- != 0 ) *d++=*s--; *d = 0;//尾部要加\0 printf(&%s\n&,dest); free(dest);// 使用完,应当释放空间,以免造成内存汇泄露 return 0; } 方法 2: #include &stdio.h& #include &string.h& main() { char str[]=&hello,world&; int len=strlen(str); for(int i=0; i&len/2; i++) { t=str[i]; str[i]=str[len-i-1]; str[len-i-1]=t; } printf(&%s&,str); return 0; } 1.-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) 答案:63 2.用两个栈实现一个队列的功能?要求给出算法和思路! 设 2 个栈为 A,B, 一开始均为空. 入队: 将新元素 push 入栈 A; 出队: (1)判断栈 B 是否为空; (2)如果不为空,则将栈 A 中所有元素依次 pop 出并 push 到栈 B; (3)将栈 B 的栈顶元素 pop 出; 这样实现的队列入队和出队的平摊复杂度都还是 O(1), 比上面的几种方法要好。3.在 c 语言 库函数中将一个字符转换成整型的函数是 atool()吗,这个函数的原型是什么? 函数名: atol 功 能: 把字符串转换成长整型数 用 法: long atol(const char *nptr); 程序例: #include &stdlib.h& #include &stdio.h& int main(void) { char *str = &&; l = atol(lstr); printf(&string = %s integer = %ld\n&, str, l); return(0); } .对于一个频繁使用的短小函数,在 C 语言中应用什么实现,在 C++中应用什么实现? c 用宏定义,c++用 inline 3.直接链接两个信令点的一组链路称作什么? PPP 点到点连接 4.接入网用的是什么接口? 5.voip 都用了那些协议? 6.软件测试都有那些种类? 黑盒:针对系统功能的测试 白合:测试函数功能,各函数接口 7.确定模块的功能和模块的接口是在软件设计的那个队段完成的? 概要设计阶段 8.enum string { x1, x2, x3=10, x4, x5, }x; 问 x= 0xx8010f4 ; 9.unsigned char *p1; unsigned long *p2; p1=(unsigned char *)0x801000; p2=(unsigned long *)0x810000; 请问 p1+5= ; p2+5= ; 三.选择题: 1.Ethternet 链接到 Internet 用到以下那个协议? A.HDLC;B.ARP;C.UDP;D.TCP;E.ID 2.属于网络层协议的是: A.TCP;B.IP;C.ICMP;D.X.25 3.Windows 消息调度机制是: A.指令队列;B.指令堆栈;C.消息队列;D.消息堆栈; 4.unsigned short hash(unsigned short key) { return (key&&)%256 } 请问 hash(16),hash(256)的值分别是: A.1.16;B.8.32;C.4.16;D.1.32 四.找错题: 1.请问下面程序有什么错误? int a[60][250][1000],i,j,k; for(k=0;k&=1000;k++) for(j=0;j&250;j++) for(i=0;i&60;i++) a[i][j][k]=0; 把循环语句内外换一下 2.#define Max_CB 500 void LmiQueryCSmd(Struct MSgCB * pmsg) { unsigned char ucCmdN ...... for(ucCmdNum=0;ucCmdNum&Max_CB;ucCmdNum++) { ......; } 死循环 3.以下是求一个数的平方的程序,请找出错误: #define SQUARE(a)((a)*(a)) int a=5; b=SQUARE(a++); 4.typedef unsigned char BYTE int examply_fun(BYTE gt_ BYTE *gt_code) { BYTE *gt_ gt_buf=(BYTE *)MALLOC(Max_GT_Length); ...... if(gt_len&Max_GT_Length) { return GT_Length_ERROR; } ....... } 五.问答题: 1.IP Phone 的原理是什么? IPV6 2.TCP/IP 通信建立的过程怎样,端口有什么作用? 三次握手,确定是哪个应用程序使用该协议 3.1 号信令和 7 号信令有什么区别,我国某前广泛使用的是那一种? 4.列举 5 种以上的电话新业务? 微软亚洲技术中心的面试题!!! 1.进程和线程的差别。 线程是指进程内的一个执行单元,也是进程内的可调度实体. 与进程的区别: (1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位 (2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行 (3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于 进程的资源. (4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销 明显大于创建或撤消线程时的开销。 2.测试方法 人工测试:个人复查、抽查和会审 机器测试:黑盒测试和白盒测试 2.Heap 与 stack 的差别。 Heap 是堆,stack 是栈。 Stack 的空间由操作系统自动分配/释放,Heap 上的空间手动分配/释放。 Stack 空间有限,Heap 是很大的自由存储区 C 中的 malloc 函数分配的内存空间即在堆上,C++中对应的是 new 操作符。 程序在编译期对变量和函数分配内存都在栈上进行,且程序运行过程中函数调用时参数的传 递也在栈上进行 3.Windows 下的内存是如何管理的? 4.介绍.Net 和.Net 的安全性。 5.客户端如何访问.Net 组件实现 Web Service? 6.C/C++编译器中虚表是如何完成的? 7.谈谈 COM 的线程模型。然后讨论进程内/外组件的差别。 8.谈谈 IA32 下的分页机制 小页(4K)两级分页模式,大页(4M)一级 9.给两个变量,如何找出一个带环单链表中是什么地方出现环的? 一个递增一,一个递增二,他们指向同一个接点时就是环出现的地方 10.在 IA32 中一共有多少种办法从用户态跳到内核态? 通过调用门,从 ring3 到 ring0,中断从 ring3 到 ring0,进入 vm86 等等 11.如果只想让程序有一个实例运行,不能运行两个。像 winamp 一样,只能开一个窗口, 怎样实现? 用内存映射或全局原子(互斥变量)、查找窗口句柄.. FindWindow,互斥,写标志到文件或注册表,共享内存。. 12.如何截取键盘的响应,让所有的?a?变成?b?? 键盘钩子 SetWindowsHookEx 13.Apartment 在 COM 中有什么用?为什么要引入? 14.存储过程是什么?有什么用?有什么优点? 我的理解就是一堆 sql 的集合,可以建立非常复杂的查询,编译运行,所以运行一次后,以 后再运行速度比单独执行 SQL 快很多 15.Template 有什么特点?什么时候用? 16.谈谈 Windows DNA 结构的特点和优点。 网络编程中设计并发服务器,使用多进程 与 多线程 ,请问有什么区别? 1,进程:子进程是父进程的复制品。子进程获得父进程数据空间、堆和栈的复制品。 2,线程:相对与进程而言,线程是一个更加接近与执行体的概念,它可以与同进程的其他 线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。 两者都可以提高程序的并发度,提高程序运行效率和响应时间。 线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源管理和保护;而进程正相 反。同时,线程适合于在 SMP 机器上运行,而进程则可以跨机器迁移。 思科 1. 用宏定义写出 swap(x,y) #define swap(x, y)\ x = x +\ y = x -\ x = x -2.数组 a[N],存放了 1 至 N-1 个数,其中某个数重复一次。写一个函数,找出被重复的数字. 时间复杂度必须为 o(N)函数原型: int do_dup(int a[],int N) ?????????????????????????? My:通过和来判断??? 3 一语句实现 x 是否为 2 的若干次幂的判断 int i = 512; cout && boolalpha && ((i & (i - 1)) ? false : true) && 4.unsigned int intvert(unsigned int x,int p,int n)实现对 x 的进行转换,p 为起始转化位,n 为需要转 换的长度,假设起始点在右边.如 x=0b,p=4,n=3 转换后 x=0b unsigned int intvert(unsigned int x,int p,int n){ unsigned int _t = 0; unsigned int _a = 1; for(int i = 0; i & ++i){ _t |= _a; _a = _a && 1; } _t = _t && x ^= _t; }慧通: 什么是预编译 何时需要预编译: 1、总是使用不经常改动的大型代码体。 2、程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。在这种 情况下,可以将所有包含文件预编译为一个预编译头。 char * char const * p const char *p 上述三个有什么区别? char * //常量指针,p 的值不可以修改 char const * p;//指向常量的指针,指向的常量值不可以改 const char *p; //和 char const *p char str1[] = &abc&; char str2[] = &abc&; const char str3[] = &abc&; const char str4[] = &abc&; const char *str5 = &abc&; const char *str6 = &abc&; char *str7 = &abc&; char *str8 = &abc&; cout && ( str1 == str2 ) && cout && ( str3 == str4 ) && cout && ( str5 == str6 ) && cout && ( str7 == str8 ) && 结果是:0 0 1 1 解答:str1,str2,str3,str4 是数组变量,它们有各自的内存空间; 而 str5,str6,str7,str8 是指针,它们指向相同的常量区域。 12. 以下代码中的两个 sizeof 用法有问题吗?[C 易] void UpperCase( char str[] ) // 将 str 中的小写字母转换成大写字母 { for( size_t i=0; i&sizeof(str)/sizeof(str[0]); ++i ) if( 'a'&=str[i] && str[i]&='z' ) str[i] -= ('a'-'A' ); } char str[] = &aBcDe&; cout && &str 字符长度为: & && sizeof(str)/sizeof(str[0]) && UpperCase( str ); cout && str && 答:函数内的 sizeof 有问题。根据语法,sizeof 如用于数组,只能测出静态数组的大小,无 法检测动态分配的或外部数组大小。函数外的 str 是一个静态定义的数组,因此其大小为 6,函数内的 str 实际只是一个指向字符串的指针,没有任何额外的与数组相关的信息,因此 sizeof 作用于上只将其 当指针看,一个指针为 4 个字节,因此返回 4。 一个 32 位的机器,该机器的指针是多少位 指针是多少位只要看地址总线的位数就行了。80386 以后的机子都是 32 的数据总线。所以 指针的位数就是 4 个字节了。 My:!!!!!!!!!!这题比较好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]. 1.请问以下代码有什么问题: int main() { 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]的赋值操作是不合法的。1、写一个“标准”宏,这个宏输入两个参数并返回较小的一个。 .#define Min(X, Y) ((X)&(Y)?(Y):(X))//结尾没有; 2、嵌入式系统中经常要用到无限循环,你怎么用 C 编写死循环。 while(1){}或者 for(;;) 3、关键字 static 的作用是什么? 定义静态变量 4、关键字 const 有什么含意? 表示常量不可以修改的变量。 5、关键字 volatile 有什么含意?并举出三个不同的例子? 提示编译器对象的值可能在编译器未监测到的情况下改变。 int (*s[10])(int) 表示的是什么啊 int (*s[10])(int) 函数指针数组,每个指针指向一个 int func(int param)的函数。 1.有以下表达式: 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; 禁止 2.交换两个变量的值,不使用第三个变量。即 a=3,b=5,交换之后 a=5,b=3; 有两种解法, 一种用算术算法, 一种用^(异或) a = a + b = a - a = a - or a = a^b;// 只能对 int,char.. b = a^b; a = a^b; or a ^= b ^= 3.c 和 c++中的 struct 有什么不同? c 和 c++中 struct 的主要区别是 c 中的 struct 不可以含有成员函数,而 c++中的 struct 可以。 c++中 struct 和 class 的主要区别在于默认的存取权限不同,struct 默认为 public,而 class 默 认为 private 4.#include &stdio.h& #include &stdlib.h& void getmemory(char *p) { p=(char *) malloc(100); strcpy(p,&hello world&); } int main( ) { char *str=NULL; getmemory(str); printf(&%s/n&,str); free(str); return 0; } 程序崩溃,getmemory 中的 malloc 不能返回动态内存, free()对 str 操作很危险 5.char szstr[10]; strcpy(szstr,&&); 产生什么结果?为什么? 长度不一样,会造成非法的 OS 6.列举几种进程的同步机制,并比较其优缺点。 原子操作 信号量机制 自旋锁 管程,会合,分布式系统 7.进程之间通信的途径 共享存储系统 消息传递系统 管道:以文件系统为基础 11.进程死锁的原因 资源竞争及进程推进顺序非法 12.死锁的 4 个必要条件 互斥、请求保持、不可剥夺、环路 13.死锁的处理 鸵鸟策略、预防策略、避免策略、检测与解除死锁 15. 操作系统中进程调度策略有哪几种? FCFS(先来先服务),优先级,时间片轮转,多级反馈 8.类的静态成员和非静态成员有何区别? 类的静态成员每个类只有一个,非静态成员每个对象一个 9.纯虚函数如何定义?使用时应注意什么? virtual void f()=0; 是接口,子类必须要实现 10.数组和链表的区别 数组:数据顺序存储,固定大小 连表:数据可以随机存储,大小可动态改变 12.ISO 的七层模型是什么?tcp/udp 是属于哪一层?tcp/udp 有何优缺点? 应用层 表示层 会话层 运输层 网络层 物理链路层 物理层 tcp /udp 属于运输层 TCP 服务提供了数据流传输、可靠性、有效流控制、全双工操作和多路复用技术等。 与 TCP 不同, UDP 并不提供对 IP 协议的可靠机制、流控制以及错误恢复功能等。由于 UDP 比较简单, UDP 头包含很少的字节,比 TCP 负载消耗少。 tcp: 提供稳定的传输服务,有流量控制,缺点是包头大,冗余性不好 udp: 不提供稳定的服务,包头小,开销小 1:(void *)ptr 和 (*(void**))ptr 的结果是否相同?其中 ptr 为同一个指针 .(void *)ptr 和 (*(void**))ptr 值是相同的 2:int main() { int x=3; printf(&%d&,x); return 1; } 问函数既然不会被其它函数调用,为什么要返回 1? mian 中,c 标准认为 0 表示成功,非 0 表示错误。具体的值是某中具体出错信息 1,要对绝对地址 0x100000 赋值,我们可以用 (unsigned int*)0x100000 = 1234; 那么要是想让程序跳转到绝对地址是 0x100000 去执行,应该怎么做? *((void (*)( ))0x100000 ) ( ); 首先要将 0x100000 强制转换成函数指针,即: (void (*)())0x100000 然后再调用它: *((void (*)())0x100000)(); 用 typedef 可以看得更直观些: typedef void(*)() voidFuncP *((voidFuncPtr)0x100000)(); 2,已知一个数组 table,用一个宏定义,求出数据的元素个数 #define NTBL #define NTBL (sizeof(table)/sizeof(table[0])) 面试题: 线程与进程的区别和联系? 线程是否具有相同的堆栈? dll 是否有独立的堆栈? 进程是死的,只是一些资源的集合,真正的程序执行都是线程来完成的,程序启动的时候操 作系统就帮你创建了一个主线程。 每个线程有自己的堆栈。 DLL 中有没有独立的堆栈,这个问题不好回答,或者说这个问题本身是否有问题。因为 DLL 中的代码是被某些线程所执 行,只有线程拥有堆栈,如果 DLL 中的代码是 EXE 中的 线程所调用,那么这个时候是不是说这个 DLL 没有自己独立的堆栈?如果 DLL 中的代码是 由 DLL 自 己创建的线程所执行,那么是不是说 DLL 有独立的堆栈? 以上讲的是堆栈,如果对于堆来说,每个 DLL 有自己的堆,所以如果是从 DLL 中动态分配 的内存,最好是从 DLL 中删除,如果你从 DLL 中分配内存,然后在 EXE 中,或者另外一 个 DLL 中删除,很有可能导致程序崩溃 unsigned short A = 10; printf(&~A = %u\n&, ~A); char c=128; printf(&c=%d\n&,c); 输出多少?并分析过程 第一题,~A =0xfffffff5,int 值 为-11,但输出的是 uint。所以输出
第二题,c=0x10,输出的是 int,最高位为 1,是负数,所以它的值就是 0x00 的补码就是 128,所以输出-128。 这两道题都是在考察二进制向 int 或 uint 转换时的最高位处理。 分析下面的程序: void GetMemory(char **p,int num) { *p=(char *)malloc(num); } int main() { char *str=NULL; GetMemory(&str,100); strcpy(str,&hello&); free(str); if(str!=NULL) { strcpy(str,&world&); } printf(&\n str is %s&,str); getchar(); } 问输出结果是什么?希望大家能说说原因,先谢谢了 输出 str is world。 free 只是释放的 str 指向的内存空间,它本身的值还是存在的. 所以 free 之后,有一个好的习惯就是将 str=NULL. 此时 str 指向空间的内存已被回收,如果输出语句之前还存在分配空间的操作的话,这段存储空 间是可能被重新分配给其他变量的, 尽管这段程序确实是存在大大的问题(上面各位已经说得很清楚了),但是通常会打印出 world 来。 这是因为,进程中的内存管理一般不是由操作系统完成的,而是由库函数自己完成的。 当 你 malloc 一块内存的时候,管理库向操作系统申请一块空间(可能会比你申请的大一 些),然后在这块空间中记录一些管理信息(一般是在你申请的内存前面 一点),并将可 用内存的地址返回。但是释放内存的时候,管理库通常都不会将内存还给操作系统,因此你 是可以继续访问这块地址的,只不过。。。。。。。。楼 上都说过了,最好别这么干。 char a[10],strlen(a)为什么等于 15?运行的结果 #include &stdio.h& #include &string.h& void main() { char aa[10]; printf(&%d&,strlen(aa)); } sizeof()和初不初始化,没有关系; strlen()和初始化有关。 char (*str)[20];/*str 是一个数组指针,即指向数组的指针.*/ char *str[20];/*str 是一个指针数组,其元素为指针型数据.*/ long a=0x801010; a+5=? 0x801010 用二进制表示为:“01 00”,十进制的值为 8392720,再加 上 5 就是 8392725 罗1)给定结构 struct A { char t:4; char k:4; unsigned short i:8; };问 sizeof(A) = ? 给定结构 struct A { char t:4; 4 位 char k:4; 4 位 unsigned short i:8; 8 位 // 偏移 2 字节保证 4 字节对齐 }; // 共 8 字节 2)下面的函数实现在一个数上加一个数,有什么错误?请改正。 int add_n ( int n ) { static int i = 100; i += } 当你第二次调用时得不到正确的结果,难道你写个函数就是为了调用一次?问题就出在 static 上? // 帮忙分析一下 #include&iostream.h& #include &string.h& #include &malloc.h& #include &stdio.h& #include &stdlib.h& #include &memory.h& typedef struct AA { int b1:5; int b2:2; }AA; void main() { AA char cc[100]; strcpy(cc,&abcdefghijklmnopqrstuvwxyz&); memcpy(&aa,cc,sizeof(AA)); cout && aa.b1 && cout && aa.b2 && } 答案是 -16 和1 首先 sizeof(AA)的大小为 4,b1 和 b2 分别占 5bit 和 2bit. 经过 strcpy 和 memcpy 后,aa 的 4 个字节所存放的值是: 0,1,2,3 的 ASC 码,即 10, 所以,最后一步:显示的是这4个字节的前5位,和之后的2位 分别为:10000,和 01 因为 int 是有正负之分 所以:答案是-16 和1 求函数返回值,输入 x=9999; int func ( x ) { int countx = 0; while ( x ) { countx ++; x = x&(x-1); } } 结果呢? 知道了这是统计 9999 的二进制数值中有多少个 1 的函数,且有 9999=9× +256+15 9× 1024 中含有 1 的个数为 2; 512 中含有 1 的个数为 1; 256 中含有 1 的个数为 1; 15 中含有 1 的个数为 4; 故共有 1 的个数为 8,结果为 8。 1000 - 1 = 0111,正好是原数取反。这就是原理。 用这种方法来求 1 的个数是很效率很高的。 不必去一个一个地移位。循环次数最少。 int a,b,c 请写函数实现 C=a+b ,不可以改变数据类型,如将 c 改为 long int,关键是如何处理溢出 问题 bool add (int a, int b,int *c) { *c=a+b; return (a&0 && b&0 &&(*c&a || *c&b) || (a&0 && b&0 &&(*c&a || *c&b))); } 分析: struct bit {int a:3; int b:2; int c:3;}; int main() { char *c=(char*)&s; cout&&sizeof(bit)&& *c=0x99; cout && s.a &&endl &&s.b&&endl&&s.c&& int a=-1; printf(&%x&,a); return 0; } 输出为什么是 4 1 -1 -4 ffffffff 因为 0x99 在内存中表示为 100 11 001 , a = 001, b = 11, c = 100 当 c 为有符合数时, c = 100, 最高 1 为表示 c 为负数,负数在计算机用补码表示,所以 c = -4; 同理 b = -1; 当 c 为有符合数时, c = 100,即 c = 4,同理 b = 3 位域 : 有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如 在存放一个开关量时,只有 0 和 1 两种状态, 用一位二进位即可。为了节省存储空间,并 使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字 节中的二进位划分为几 个不同的区域, 并说明每个区域的位数。每个域有一个域名,允许 在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来表 示。一、位域的定义和位域变量的说明位域定义与结构定义相仿,其形式为: struct 位域结构名 { 位域列表 }; 其中位域列表的形式为: 类型说明符 位域名:位域长度 例如: struct bs { int a:8; int b:2; int c:6; }; 位域变量的说明与结构变量说明的方式相同。 可采用先定义后说明,同时定义说明或者直 接说明这三种方式。例如: struct bs { int a:8; int b:2; int c:6; } 说明 data 为 bs 变量,共占两个字节。其中位域 a 占 8 位,位域 b 占 2 位,位域 c 占 6 位。 对于位域的定义尚有以下几点说明: 1. 一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另 一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。例如: struct bs { unsigned a:4 unsigned :0 /*空域*/ unsigned b:4 /*从下一单元开始存放*/ unsigned c:4 } 在这个位域定义中,a 占第一字节的 4 位,后 4 位填 0 表示不使用,b 从第二字节开始,占 用 4 位,c 占用 4 位。 2. 由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度,也就是说不能 超过 8 位二进位。 3. 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例 如: struct k { int a:1 int :2 /*该 2 位不能使用*/ int b:3 int c:2 }; 从以上分析可以看出,位域在本质上就是一种结构类型, 不过其成员是按二进位分配 的。 二、位域的使用位域的使用和结构成员的使用相同,其一般形式为: 位域变量名?位域名 位域允许用各种格式输出。 main(){ struct bs { unsigned a:1; unsigned b:3; unsigned c:4; } bit,* bit.a=1; bit.b=7; bit.c=15; pri 改错: #include &stdio.h& int main(void) { int **p; int arr[100]; p = & return 0; } 解答: 搞错了,是指针类型不同, int **p; //二级指针 & //得到的是指向第一维为 100 的数组的指针 #include &stdio.h& int main(void) { int **p, *q; int arr[100]; q = p = &q; return 0; } 下面这个程序执行后会有什么错误或者效果: #define MAX 255 int main() { unsigned char A[MAX],i;//i 被定义为 unsigned char for (i=0;i&=MAX;i++) A[i]=i; } 解答:死循环加数组越界访问(C/C++不进行数组越界检查) MAX=255 数组 A 的下标范围为:0..MAX-1,这是其一.. 其二.当 i 循环到 255 时,循环内执行: A[255]=255; 这句本身没有问题..但是返回 for (i=0;i&=MAX;i++)语句时, 由于 unsigned char 的取值范围在(0..255),i++以后 i 又为 0 了..无限循环下去. struct name1{ } struct name2{ } sizeof(struct name1)=8,sizeof(struct name2)=12 在第二个结构中,为保证 num 按四个字节对齐,char 后必须留出 3 字节的空间;同时为保 证整个结构的自然对齐(这里是 4 字节对齐),在 x 后还要补齐 2 个字节,这样就是 12 字 节。 intel: A.c 和 B.c 两个 c 文件中使用了两个相同名字的 static 变量,编译的时候会不会有问题?这两个 static 变量会保存到哪里(栈还是堆或者其他的)? static 的全局变量,表明这个变量仅在本模块中有意义,不会影响其他模块。 他们都放在数据区,但是编译器对他们的命名是不同的。 如果要使变量在其他模块也有意义的话,需要使用 extern 关键字。 struct s1 { int i: 8; int j: 4; int a: 3; }; struct s2 { int i: 8; int j: 4; int a:3; }; printf(&sizeof(s1)= %d\n&, sizeof(s1)); printf(&sizeof(s2)= %d\n&, sizeof(s2)); result: 16, 24 第一个 struct s1 { int i: 8; int j: 4; int a: 3; }; 理 论上是这样的,首先是 i 在相对 0 的位置,占 8 位一个字节,然后,j 就在相对一个字节 的位置,由于一个位置的字节数是 4 位的倍数,因此不用对齐,就放在那里 了,然后是 a,要在 3 位的倍数关系的位置上,因此要移一位,在 15 位的位置上放下,目前总共是 18 位,折算过来是 2 字节 2 位的样子,由于 double 是 8 字节的,因此要在相对 0 要是 8 个字 节的位置上放下,因此从 18 位开始到 8 个字节之间的位置被忽略,直接放在 8 字节的位置 了,因此,总共是 16 字节。 第二个最后会对照是不是结构体内最大数据的倍数,不是的话,会补成是最大数据的倍数上面是基本问题,接下来是编程问题: 本人很弱,这几个题也搞不定,特来求救: 1)读文件 file1.txt 的内容(例如): 12 34 56 输出到 file2.txt: 56 34 12 (逆序) 2)输出和为一个给定整数的所有组合 例如 n=5 5=1+4;5=2+3(相加的数不能重复) 则输出 1,4;2,3。 望高手赐教!! 第一题,注意可增长数组的应用. #include &stdio.h& #include &stdlib.h& int main(void) { int MAX = 10; int *a = (int *)malloc(MAX * sizeof(int)); int *b; FILE *fp1; FILE *fp2; fp1 = fopen(&a.txt&,&r&); if(fp1 == NULL) {printf(&error1&); exit(-1); } fp2 = fopen(&b.txt&,&w&); if(fp2 == NULL) {printf(&error2&); exit(-1); } int i = 0; int j = 0; while(fscanf(fp1,&%d&,&a[i]) != EOF) { i++; j++; if(i &= MAX) { MAX = 2 * MAX; b = (int*)realloc(a,MAX * sizeof(int)); if(b == NULL) { printf(&error3&); exit(-1); } a = } } for(;--j &= 0;) fprintf(fp2,&%d\n&,a[j]); fclose(fp1); fclose(fp2); return 0; } 第二题. #include &stdio.h& int main(void) { unsigned long int i,j,k; printf(&please input the number\n&); scanf(&%d&,&i); if( i % 2 == 0) j = i / 2; else j = i / 2 + 1; printf(&The result is \n&); for(k = 0; k & k++) printf(&%d = %d + %d\n&,i,k,i - k); return 0; } #include &stdio.h& void main() { unsigned long int a,i=1; scanf(&%d&,&a); if(a%2==0) { for(i=1;i&a/2;i++) printf(&%d&,a,a-i); } else for(i=1;i&=a/2;i++) printf(& %d, %d&,i,a-i); } 兄弟,这样的题目若是做不出来实在是有些不应该, 给你一个递规反向输出字符串的例子,可 谓是反序的经典例程. void inverse(char *p) { if( *p = = '\0' ) inverse( p+1 ); printf( &%c&, *p ); } int main(int argc, char *argv[]) { inverse(&abc\0&); return 0; } 借签了楼上的“递规反向输出” #include &stdio.h& void test(FILE *fread, FILE *fwrite) { char buf[1024] = {0}; if (!fgets(buf, sizeof(buf), fread)) test( fread, fwrite ); fputs(buf, fwrite); } int main(int argc, char *argv[]) { FILE *fr = NULL; FILE *fw = NULL; fr = fopen(&data&, &rb&); fw = fopen(&dataout&, &wb&); test(fr, fw); fclose(fr); fclose(fw); return 0; } 在对齐为 4 的情况下 struct BBB { long num; char * short ba[5]; }*p; p=0x1000000; p+0x200=____; (Ulong)p+0x200=____; (char*)p+0x200=____; 希望各位达人给出答案和原因,谢谢拉 解答:假设在 32 位 CPU 上, sizeof(long) = 4 bytes sizeof(char *) = 4 bytes sizeof(short int) = sizeof(short) = 2 bytes sizeof(char) = 1 bytes 由于是 4 字节对齐, sizeof(struct BBB) = sizeof(*p) = 4 + 4 + 2 + 1 + 1/*补齐*/ + 2*5 + 2/*补齐*/ = 24 bytes (经 Dev-C++验证) p=0x1000000; p+0x200=____; = 0x1000000 + 0x200*24 (Ulong)p+0x200=____; = 0x1000000 + 0x200 (char*)p+0x200=____; = 0x1000000 + 0x200*4 你可以参考一下指针运算的细节 写一段程序,找出数组中第 k 大小的数,输出数所在的位置。例如{2,4,3,4,7}中,第 一大的数是 7,位置在 4。第二大、第三大的数都 是 4,位置在 1、3 随便输出哪一个均 可。函数接口为:int find_orderk(const int* narry,const int n,const int k) 要求算法复杂度不能是 O(n^2) 谢谢! 可以先用快速排序进行排序,其中用另外一个进行地址查找 代码如下,在 VC++6.0 运行通过。给分吧^-^ //快速排序 #include&iostream& intPartition (int*L,intlow,int high) { inttemp = L[low]; intpt = L[low]; while (low & high) { while (low & high && L[high] &= pt) -- L[low] = L[high]; while (low & high && L[low] &= pt) ++ L[low] = } L[low] = } voidQSort (int*L,intlow,int high) { if (low & high) { intpl = Partition (L,low,high); QSort (L,low,pl - 1); QSort (L,pl + 1,high); } } intmain () { intnarry[100],addr[100]; intsum = 1,t; cout && &Input number:& && cin && while (t != -1) { narry[sum] = addr[sum - 1] = sum++; cin && } sum -= 1; QSort (narry,1,sum); for (int i = 1; i &=i++) cout && narry[i] && '\t'; cout && cout && &Please input place you want:& && cin && intaa = 1; intkk = 0; for (;;) { if (aa == k) if (narry[kk] != narry[kk + 1]) { aa += 1; kk++; } } cout && &The NO.& && k && &number is:& && narry[sum - kk] && cout && &And it's place is:& ; for (i = 0;i &i++) { if (addr[i] == narry[sum - kk]) cout && i && '\t'; } return0; } 1、找错 Void test1() { char string[10]; char* str1=&&; strcpy(string, str1);// 溢出,应该包括一个存放'\0'的字符 string[11] } Void test2() { char string[10], str1[10]; for(I=0; I&10;I++) { str1[i] ='a'; } strcpy(string, str1);// I,i 没有声明。 } Void test3(char* str1) { char string[10]; if(strlen(str1)&=10)// 改成&10,字符溢出,将 strlen 改为 sizeof 也可以 { strcpy(string, str1); } } 2. void g(int**); int main() { int line[10],i; int *p= //p 是地址的地址 for (i=0;i&10;i++) { *p=i; g(&p);//数组对应的值加 1 } for(i=0;i&10;i++) printf(&%d\n&,line[i]); return 0; } void g(int**p) { (**p)++; (*p)++;// 无效 } 输出: 1 2 3 4 5 6 7 8 9 10 3. 写出程序运行结果 int sum(int a) { auto int c=0; static int b=3; c+=1; b+=2; return(a+b+c); } void main() { int I; int a=2; for(I=0;I&5;I++) { printf(&%d,&, sum(a)); } } // static 会保存上次结果,记住这一点,剩下的自己写 输出:8,10,12,14,16, 4. int func(int a) { switch(a) { case 1: 30; case 2: 20; case 3: 16; default: 0 } } 则 func(1)=? // b 定义后就没有赋值。 5: int a[3]; a[0]=0; a[1]=1; a[2]=2; int *p, *q; p=a; q=&a[2]; 则 a[q-p]=a[2] 解释:指针一次移动一个 int 但计数为 1 今天早上的面试题 9 道,比较难,向牛人请教,国内的一牛公司,坐落在北京北四环某大 厦: 1、线形表 a、b 为两个有序升序的线形表,编写一程序,使两个有序线形表合并成一个有序 升序线形表 h; 答案在 请化大学 严锐敏《数据结构第二版》第二章例题,数据结构当中,这个叫做:两路 归并排序 Linklist *unio(Linklist *p,Linklist *q){ linklist *R,*pa,*qa,* pa=p; qa=q; R=ra=p; while(pa-&next!=NULL&&qa-&next!=NULL){ if(pa-&data&qa-&data){ ra-&next= qa=qa-& } else{ ra-&next= pa=pa-& } } if(pa-&next!=NULL) ra-&next= if(qa-&next!=NULL) ra-&next== return R; } 2、运用四色定理,为 N 个局域举行配色,颜色为 1、2、3、4 四种,另有数组 adj[][N],如 adj[i][j]=1 则表示 i 区域与 j 区域相邻,数组 color[N],如 color[i]=1,表示 i 区域的颜色为 1 号 颜色。 四色填充 3、用递归算法判断数组 a[N]是否为一个递增数组。 递归的方法,记录当前最大的,并且判断当前的是否比这个还大,大则继续,否则返回 false 结束: bool fun( int a[], int n ) { if( n= =1 ) if( n= =2 ) return a[n-1] &= a[n-2]; return fun( a,n-1) && ( a[n-1] &= a[n-2] ); } 4、编写算法,从 10 亿个浮点数当中,选出其中最大的 10000 个。 用外部排序,在《数据结构》书上有 《计算方法导论》在找到第 n 大的数的算法上加工 5、编写一 unix 程序,防止僵尸进程的出现. 同学的 4 道面试题,应聘的职位是搜索引擎工程师,后两道超级难,(希望大家多给一些算 发) 1.给两个数组和他们的大小,还有一动态开辟的内存,求交集,把交集放到动态内存 dongtai,并且返回交集个数 long jiaoji(long* a[],long b[],long* alength,long blength,long* dongtai[]) 2.单连表的建立,把'a'--'z'26 个字母插入到连表中,并且倒叙,还要打印! 方法 1: typedef struct val { int date_1; struct val * }*p; void main(void) { for(c=122;c&=97;c--) { p.date=c; p=p-& }p.next=NULL; } } 方法 2: node *p = NULL; node *q = NULL; node *head = (node*)malloc(sizeof(node)); head-&data = ' ';head-&next=NULL; node *first = (node*)malloc(sizeof(node)); first-&data = 'a';first-&next=NULL;head-&next = p = int longth = 'z' - 'b'; int i=0; while ( i&=longth ) { node *temp = (node*)malloc(sizeof(node)); temp-&data = 'b'+i;temp-&next=NULL;q= head-&next = temp-&next=p;p=q; i++; } print(head); 3.可怕的题目终于来了 象搜索的输入信息是一个字符串,统计 300 万输入信息中的最热门的前十条,我们每次输入 的一个字符串为不超过 255byte,内存使用只有 1G, 请描述思想,写出算发(c 语言),空间和时间复杂度, 4.国内的一些帖吧,如 baidu,有几十万个主题,假设每一个主题都有上亿的跟帖子,怎么样 设计这个系统速度最好,请描述思想,写出算发(c 语言),空间和时间复杂度, #include string.h main(void) { char *src=&hello,world&; char *dest=NULL; dest=(char *)malloc(strlen(src)); int len=strlen(str); char *d= char *s=src[len]; while(len--!=0) d++=s--; printf(&%s&,dest); } 找出错误!! #include &string.h& #include &stdio.h& #include &malloc.h& main(void) { char *src=&hello,world&; char *dest=NULL; dest=(char *)malloc(sizeof(char)*(strlen(src)+1)); int len=strlen(src); char *d= char *s=src+len-1; while(len--!=0) *d++=*s--; *d='\0'; printf(&%s&,dest); } 1. 简述一个 Linux 驱动程序的主要流程与功能。 2. 请列举一个软件中时间换空间或者空间换时间的例子。 void swap(int a,int b) { c=a;a=b;b=a; } ---&空优 void swap(int a,int b) { a=a+b;b=a-b;a=a-b; } 6. 请问一下程序将输出什么结果? char *RetMenory(void) { char p[] = “hellow world”; } void Test(void) { char *str = NULL; str = RetMemory(); printf(str); } RetMenory 执行完毕,p 资源被回收,指向未知地址。返回地址,str 的内容应是不可预测的, 打印的应该是 str 的地址 写一个函数,它的原形是 int continumax(char *outputstr,char *intputstr) 功能: 在字符串中找出连续最长的数字串,并把这个串的长度返回,并把这个最长数字串付给其中 一个函数参数 outputstr 所指内存。例如:&abcd1ss&的首地址传给 intputstr 后,函数将返回 9,outputstr 所指的值为
int continumax(char *outputstr, char *inputstr) { char *in = inputstr, *out = outputstr, *temp, * int count = 0, maxlen = 0; while( *in != '\0' ) { if( *in & 47 && *in & 58 ) { for(temp = *in & 47 && *in & 58 ; in++ ) count++; } else in++; if( maxlen & count ) { maxlen = count = 0; final = } } for(int i = 0; i & i++) { *out = * out++; final++; } *out = '\0'; } 不用库函数,用 C 语言实现将一整型数字转化为字符串 方法 1: int getlen(char *s){ for(n = 0; *s != '\0'; s++) n++; } void reverse(char s[]) { int c,i,j; for(i = 0,j = getlen(s) - 1; i & i++,j--){ c = s[i]; s[i] = s[j]; s[j] = } } void itoa(int n,char s[]) { int i, if((sign = n) & 0) n = -n; i = 0; do{/*以反序生成数字*/ s[i++] = n%10 + '0';/*get next number*/ }while((n /= 10) & 0);/*delete the number*/ if(sign & 0) s[i++] = '-'; s[i] = '\0'; reverse(s); } 方法 2: #include &iostream& void itochar(int num); void itochar(int num) { int i = 0; char stra[10]; char strb[10]; while ( num ) { stra[i++]=num%10+48; num=num/10; } stra[i] = '\0'; for( j=0; j & j++) { strb[j] = stra[i-j-1]; } strb[j] = '\0'; cout&&strb&& } int main() { cin&& itochar(num); return 0; } 前几天面试,有一题想不明白,请教大家! typedef struct { int a:2; int b:2; int c:1; } t.a = 1; t.b = 3; t.c = 1; printf(&%d&,t.a); printf(&%d&,t.b); printf(&%d&,t.c); 谢谢! t.a 为 01,输出就是 1 t.b 为 11,输出就是-1 t.c 为 1,输出也是-1 3 个都是有符号数 int 嘛。 这是位扩展问题 01 11 1 编译器进行符号扩展 求组合数: 求 n 个数(1....n)中 k 个数的组合.... 如:combination(5,3) 要求输出:543,542,541,532,531,521,432,431,421,321, #include&stdio.h& int pop(int *); int push(int ); void combination(int ,int ); int stack[3]={0}; top=-1; int main() { int n,m; printf(&Input two numbers:\n&); while( (2!=scanf(&%d%*c%d&,&n,&m)) ) { fflush(stdin); printf(&Input error! Again:\n&); } combination(n,m); printf(&\n&); } void combination(int m,int n) { int temp=m; push(temp); while(1) { if(1==temp) { if(pop(&temp)&&stack[0]==n) //当栈底元素弹出&&为可能取的最小值,循环退出 } else if( push(--temp)) { printf(&%d%d%d &,stack[0],stack[1],stack[2]);//§ &¨¤ ì@? pop(&temp); } } } int push(int i) { stack[++top]=i; if(top&2) return 0; else return 1; } int pop(int *i) { *i=stack[top--]; if(top&=0) return 0; else return 1; } 1、用指针的方法,将字符串“ABCD1234efgh”前后对调显示 #include &stdio.h& #include &string.h& #include &dos.h& int main() { char str[] = &ABCD1234efgh&; int length = strlen(str); char * p1 = char * p2 = str + length - 1; while(p1 & p2) { char c = *p1; *p1 = *p2; *p2 = ++p1; --p2; } printf(&str now is %s\n&,str); system(&pause&); return 0; } 2、有一分数序列:1/2,1/4,1/6,1/8……,用函数调用的方法,求此数列前 20 项的和 #include &stdio.h& double getValue() { double result = 0; int i = 2; while(i & 42) { result += 1.0 ///一定要使用 1.0 做除数,不能用 1,否则结果将自动转化成整数,即 0.000000 i += 2; } } int main() { printf(&result is %f\n&, getValue()); system(&pause&); return 0; }有一个数组 a[1000]存放 0--1000;要求每隔二个数删掉一个数,到末尾时循环至开头继续进 行,求最后一个被删掉的数的原始下标位置。 以 7 个数为例: {0,1,2,3,4,5,6,7} 0--&1--&2(删除)--&3--&4--&5(删除)--&6--&7--&0(删除),如此循环直到 最后一个数被删除。 方法 1:数组 #include &iostream& #define null 1000 int main() { int arr[1000]; for (int i=0;i&1000;++i) arr[i]=i; int j=0; int count=0; while(count&999) { while(arr[j%1000]==null) j=(++j)%1000; j=(++j)%1000; while(arr[j%1000]==null) j=(++j)%1000; j=(++j)%1000; while(arr[j%1000]==null) j=(++j)%1000; arr[j]= ++ } while(arr[j]==null) j=(++j)%1000; cout&&j&& return 0; }方法 2:链表 #include&iostream& #define null 0 struct node { node* }; int main() { node* head= head-&data=0; head-&next= node* p= for(int i=1;i&1000;i++) { node* tmp= tmp-&data=i; tmp-&next= head-&next= head=head-& } head-&next=p; while(p!=p-&next) { p-&next-&next=p-&next-&next-& p=p-&next-& } cout&&p-& return 0; } 方法 3:通用算法 #include &stdio.h& #define MAXLINE 1000 //元素个数 /* MAXLINE 元素个数 a[] 元素数组 R[] 指针场 suffix 下标 index 返回最后的下标序号 values 返回最后的下标对应的值 start 从第几个开始 K 间隔 */ int find_n(int a[],int R[],int K,int& index,int& values,int s=0) { int front_node,current_ suffix=0; if(s==0) { current_node=0; front_node=MAXLINE-1; } else { current_node=s; front_node=s-1; } while(R[front_node]!=front_node) { printf(&%d\n&,a[current_node]); R[front_node]=R[current_node]; if(K==1) { current_node=R[front_node]; } for(int i=0;i&K;i++){ front_node=R[front_node]; } current_node=R[front_node]; } index=front_ values=a[front_node]; return 0; } int main(void) { int a[MAXLINE],R[MAXLINE],suffix,index,values,start,i,K; suffix=index=values=start=0; K=2; for(i=0;i&MAXLINE;i++) { a[i]=i; R[i]=i+1; } R[i-1]=0; find_n(a,R,K,index,values,2); printf(&the value is %d,%d\n&,index,values); return 0; } 试题: void test2() { char string[10], str1[10]; for(i=0; i&10; i++) { str1[i] = 'a'; } strcpy( string, str1 ); } 解 答:对试题 2,如果面试者指出字符数组 str1 不能在数组内结束可以给 3 分;如果面试 者指出 strcpy(string, str1)调用使得从 str1 内存起复制到 string 内存起所复制的字节数具有不 确定性可以给 7 分,在此基础上指出库函数 strcpy 工作方式的给 10 分; str1 不能在数组内结束:因为 str1 的存储为:{a,a,a,a,a,a,a,a,a,a},没有'\0'(字符串结束符),所以 不能结束 strcpy( char *s1,char *s2)他的工作原理是,扫描 s2 指向的内存,逐个字符付到 s1 所指向的内 存,直到碰到'\0',因为 str1 结尾没有'\0',所以具有不确定性,不知道他后面还会付什么东 东。 正确应如下 void test2() { char string[10], str1[10]; for(i=0; i&9; i++) { str1[i] = 'a'+i; //把 abcdefghi 赋值给字符数组 } str[i]='\0';//加上结束符 strcpy( string, str1 ); } 第二个 code 题是实现 strcmp int StrCmp(const char *str1, const char *str2) 做是做对了,没有抄搞,比较乱 int StrCmp(const char *str1, const char *str2) { assert(str1 && srt2); while (*str1 && *str2 && *str1 == *str2) { str1++, str2++; } if (*str1 && *str2) return (*str1-*str2); elseif (*str1 && *str2==0) return 1; elseif (*str1 = = 0 && *str2) return -1; else return 0; } int StrCmp(const char *str1, const char *str2) { //省略判断空指针(自己保证) while(*str1 && *str1++ = = *str2++); return *str1-*str2; } 第三个 code 题是实现子串定位 int FindSubStr(const char *MainStr, const char *SubStr) 做是做对了,没有抄搞,比较乱 int MyStrstr(const char* MainStr, const char* SubStr) { const char *p; const char *q; const char * u = MainS //assert((MainStr!=NULL)&&( SubStr!=NULL));//用断言对输入进行判断 while(*MainStr) //内部进行递增 { p = MainS q = SubS while(*q && *p && *p++ == *q++); if(!*q ) { return MainStr - u +1 ;//MainStr 指向当前起始位,u 指向 } MainStr ++; } return -1; } 分析: int arr[] = {6,7,8,9,10}; int *ptr = *(ptr++)+=123; printf(“ %d %d ”, *ptr, *(++ptr)); 输出:8 8 过程:对于*(ptr++)+=123;先做加法 6+123,然后++,指针指向 7;对于 printf(“ %d %d ”, *ptr, *(++ptr));从后往前执行,指针先++,指向 8,然后输出 8,紧接着再输出 8 华为全套完整试题 高级题 6、已知一个单向链表的头,请写出删除其某一个结点的算法,要求,先找到此结点,然后 删除。 slnodetype *Delete(slnodetype *Head,int key){}中 if(Head-&number==key) { Head=Pointer-& free(Pointer); } Back = P Pointer=Pointer-& if(Pointer-&number==key) { Back-&next=Pointer-& free(Pointer); } void delete(Node* p) { if(Head = Node) while(p) } 有一个 16 位的整数,每 4 位为一个数,写函数求他们的和。 解释: 整数 0111 和 11+0111 感觉应该不难,当时对题理解的不是很清楚,所以写了一个函数,也不知道对不对。 疑问: 既然是 16 位的整数,0111 是 2 进制的,那么函数参数怎么定义呢,请大虾 指教。 答案:用十进制做参数,计算时按二进制考虑。 /* n 就是 16 位的数,函数返回它的四个部分之和 */ char SumOfQuaters(unsigned short n) { char c = 0; int i = 4; do { c += n & 15; n = n && 4; } while (--i); } 有 1,2,....一直到 n 的无序数组,求排序算法,并且要求时间复杂度为 O(n),空间复杂度 O(1),使用 交换,而且一次只能交换两个数.(华为) #include&iostream.h& int main() { int a[] = {10,6,9,5,2,8,4,7,1,3}; int len = sizeof(a) / sizeof(int); for(int i = 0; i & ) { temp = a[a[i] - 1]; a[a[i] - 1] = a[i]; a[i] = if ( a[i] == i + 1) i++; } for (int j = 0; j & j++) cout&&a[j]&&&,&; return 0; } (慧通) 1 写出程序把一个链表中的接点顺序倒排 typedef struct linknode { struct linknode * } //将一个链表逆置 node *reverse(node *head) { node *p,*q,*r; p= q=p-& while(q!=NULL) { r=q-& q-&next=p; p=q; q=r; } head-&next=NULL; head=p; } 2 写出程序删除链表中的所有接点 void del_all(node *head) { node *p; while(head!=NULL) { p=head-& free(head); head=p; } cout&&&释放空间成功!&&& } 3 两个字符串,s,t;把 t 字符串插入到 s 字符串中,s 字符串有足够的空间存放 t 字符串 void insert(char *s, char *t, int i) { char *q = char *p =s; if(q == NULL) while(*p!='\0') { p++; } while(*q!=0) { *p=*q; p++; q++; } *p = '\0'; } 分析下面的代码: char *a = &hello&; char *b = &hello&; if(a= =b) printf(&YES&); else printf(&NO&); 这个简单的面试题目,我选输出 no(对比的应该是指针地址吧),可在 VC 是 YES 在 C 是 NO lz 的呢,是一个常量字符串。位于静态存储区,它在程序生命期内恒定不变。如果编译器优 化的话,会有可能 a 和 b 同时指向同一个 hello 的。则地址相同。如果编译器没有优化,那 么就是两个不同的地址,则不同写一个函数,功能:完成内存之间的拷贝 memcpy source code: 270 void* memcpy( void *dst, const void *src, unsigned int len ) 271 { 272 register char *d; 273 register char *s; 27 275 if (len == 0) 276 277 278 if (is_overlap(dst, src, len, len)) 279 complain3(&memcpy&, dst, src, len); 280 281 if ( dst & src ) { 282 d = (char *)dst + len - 1; 283 s = (char *)src + len - 1; 284 while ( len &= 4 ) { 285 *d-- = *s--; 286 *d-- = *s--; 287 *d-- = *s--; 288 *d-- = *s--; 289 len -= 4; 290 } 291 while ( len-- ) { 292 *d-- = *s--; 293 } 294 } else if ( dst & src ) { 295 d = (char *) 296 s = (char *) 297 while ( len &= 4 ) { 298 *d++ = *s++; 299 *d++ = *s++; 300 *d++ = *s++; 301 *d++ = *s++; 302 len -= 4; 303 } 304 while ( len-- ) { 305 *d++ = *s++; 306 } 307 } 308 309 } 公司考试这种题目主要考你编写的代码是否考虑到各种情况,是否安全(不会溢出) 各种情况包括: 1、参数是指针,检查指针是否有效 2、检查复制的源目标和目的地是否为同一个,若为同一个,则直接跳出 3、读写权限检查 4、安全检查,是否会溢出 memcpy 拷贝一块内存,内存的大小你告诉它 strcpy 是字符串拷贝,遇到'\0'结束 /* memcpy ─── 拷贝不重叠的内存块 */ void memcpy(void* pvTo, void* pvFrom, size_t size) { void* pbTo = (byte*)pvTo; void* pbFrom = (byte*)pvF ASSERT(pvTo != NULL && pvFrom != NULL); //检查输入指针的有效性 ASSERT(pbTo&=pbFrom+size || pbFrom&=pbTo+size);//检查两个指针指向的内存是否重叠 while(size--&0) *pbTo++ == *pbFrom++; return(pvTo); } 华为面试题:怎么判断链表中是否有环? bool CircleInList(Link* pHead) { if(pHead = = NULL || pHead-&next = = NULL)//无节点或只有一个节点并且无自环 return (false); if(pHead-&next = = pHead)//自环 return (true); Link *pTemp1 = pH//step 1 Link *pTemp = pHead-&//step 2 while(pTemp != pTemp1 && pTemp != NULL && pTemp-&next != NULL) { pTemp1 = pTemp1-& pTemp = pTemp-&next-& } if(pTemp = = pTemp1) return (true); return (false); } 两个字符串,s,t;把 t 字符串插入到 s 字符串中,s 字符串有足够的空间存放 t 字符串 void insert(char *s, char *t, int i) { memcpy(&s[strlen(t)+i],&s[i],strlen(s)-i); memcpy(&s[i],t,strlen(t)); s[strlen(s)+strlen(t)]='\0'; } 1。编写一个 C 函数,该函数在一个字符串中找到可能的最长的子字符串,且该字符串是 由同一字符组成的。 char * search(char *cpSource, char ch) { char *cpTemp=NULL, *cpDest=NULL; int iTemp, iCount=0; while(*cpSource) { if(*cpSource == ch) { iTemp = 0; cpTemp = cpS while(*cpSource == ch) ++iTemp, ++cpS if(iTemp & iCount) iCount = iTemp, cpDest = cpT if(!*cpSource) } ++cpS } return cpD } 2。请编写一个 C 函数,该函数在给定的内存区域搜索给定的字符,并返回该字符所在位 置索引值。 int search(char *cpSource, int n, char ch) { for(i=0; i&n && *(cpSource+i) != ++i); } 一个单向链表,不知道头节点,一个指针指向其中的一个节点,问如何删除这个指针指向的 节点? 将这个指针指向的 next 节点值 copy 到本节点,将 next 指向 next-&next,并随后删除原 next 指 向的节点。 #include &stdio.h& void foo(int m, int n) { printf(&m=%d, n=%d\n&, m, n); } int main() { int b = 3; foo(b+=3, ++b); printf(&b=%d\n&, b); return 0; } 输出:m=7,n=4,b=7(VC6.0) 这种方式和编译器中得函数调用关系相关即先后入栈顺序。不过不同 编译器得处理不同。也是因为 C 标准中对这种方式说明为未定义,所以 各个编译器厂商都有自己得理解,所以最后产生得结果完全不同。 因为这样,所以遇见这种函数,我们首先要考虑我们得编译器会如何处理 这样得函数,其次看函数得调用方式,不同得调用方式,可能产生不同得 结果。最后是看编译器优化。 2.写一函数,实现删除字符串 str1 中含有的字符串 str2. 第二个就是利用一个 KMP 匹配算法找到 str2 然后删除(用链表实现的话,便捷于数组) /*雅虎笔试题(字符串操作) 给定字符串 A 和 B,输出 A 和 B 中的最大公共子串。 比如 A=&aocdfe& B=&pmcdfa& 则输出&cdf& */ //Author: azhen #include&stdio.h& #include&stdlib.h& #include&string.h& char *commanstring(char shortstring[], char longstring[]) { int i, char *substring=malloc(256); if(strstr(longstring, shortstring)!=NULL) for(i=strlen(shortstring)-1;i&0; i--) { for(j=0; j&=strlen(shortstring)-i; j++){ memcpy(substring, &shortstring[j], i); substring[i]='\0'; if(strstr(longstring, substring)!=NULL) } } return NULL; } main() { char *str1=malloc(256); char *str2=malloc(256); char *comman=NULL; gets(str1); gets(str2); if(strlen(str1)&strlen(str2)) comman=commanstring(str2, str1); else comman=commanstring(str1, str2); //将短的字符串放前面 //如果……,那么返回 shortstring //否则,开始循环计算printf(&the longest comman string is: %s\n&, comman); } 11.写一个函数比较两个字符串 str1 和 str2 的大小,若相等返回 0,若 str1 大于 str2 返回 1,若 str1 小于 str2 返回-1 int strcmp ( const char * src,const char * dst) { int ret = 0 ; while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst) { ++ ++ } if ( ret & 0 ) ret = -1 ; else if ( ret & 0 ) ret = 1 ; return( ret ); }3,求 1000!的未尾有几个 0(用素数相乘的方法来做,如 72=2*2*2*3*3); 求出 1-&1000 里,能被 5 整除的数的个数 n1,能被 25 整除的数的个数 n2,能被 125 整除的数的 个数 n3, 能被 625 整除的数的个数 n4. 1000!末尾的零的个数=n1+n2+n3+n4; #include&stdio.h& #define NUM 1000 int find5(int num){ int ret=0; while(num%5==0){ num/=5; ret++; } } int main(){ int result=0; for(i=5;i&=NUM;i+=5) { result+=find5(i); } printf(& the total zero number is %d\n&,result); return 0; }1. 有双向循环链表结点定义为: struct node { struct node *front,* }; 有两个双向循环链表 A,B,知道其头指针为:pHeadA,pHeadB,请写一函数将两链表中 data 值相同的结点删除 BOOL DeteleNode(Node *pHeader, DataType Value) { if (pHeader == NULL) BOOL bRet = FALSE; Node *pNode = pH while (pNode != NULL) { if (pNode-&data == Value) { if (pNode-&front == NULL) { pHeader = pNode-& pHeader-&front = NULL; } else { if (pNode-&next != NULL) { pNode-&next-&front = pNode-& } pNode-&front-&next = pNode-& } Node *pNextNode = pNode-& delete pN pNode = pNextN bRet = TRUE; //不要 break 或 return, 删除所有 } else { pNode = pNode-& } } return bR } void DE(Node *pHeadA, Node *pHeadB) { if (pHeadA == NULL || pHeadB == NULL) { } Node *pNode = pHeadA; while (pNode != NULL) { if (DeteleNode(pHeadB, pNode-&data)) { if (pNode-&front == NULL) { pHeadA = pNode-& pHeadA-&front = NULL; } else { pNode-&front-&next = pNode-& if (pNode-&next != NULL) { pNode-&next-&front = pNode-& } } Node *pNextNode = pNode-& delete pN pNode = pNextN } else { pNode = pNode-& } } } 2. 编程实现:找出两个字符串中最大公共子字符串,如&abccade&,&dgcadde&的最大子串为&cad& int GetCommon(char *s1, char *s2, char **r1, char **r2) { int len1 = strlen(s1); int len2 = strlen(s2); int maxlen = 0; for(int i = 0; i & len1; i++) { for(int j = 0; j & len2; j++) { if(s1[i] == s2[j]) { int as = i, bs = j, count = 1; while(as + 1 & len1 && bs + 1 & len2 && s1[++as] == s2[++bs]) count++; if(count & maxlen) { maxlen = *r1 = s1 + *r2 = s2 + } } } } 3. 编程实现:把十进制数(long 型)分别以二进制和十六进制形式输出,不能使用 printf 系列 库函数 char* test3(long num) { char* buffer = (char*)malloc(11); buffer[0] = '0'; buffer[1] = 'x'; buffer[10] = '\0'; char* temp = buffer + 2; for (int i=0; i & 8; i++) { temp[i] = (char)(num&&4*i&&28); temp[i] = temp[i] &= 0 ? temp[i] : temp[i] + 16; temp[i] = temp[i] & 10 ? temp[i] + 48 : temp[i] + 55; } }输入 N, 打印 N*N 矩阵 比如 N = 3,打印: 1 2 3 8 9 4 7 6 5 N = 4,打印: 1 2 3 4 12 13 14 5 11 16 15 6 10 9 8 7 解答: 1 #define N 15 int s[N][N]; void main() { int k = 0, i = 0, j = 0; int a = 1; for( ; k & (N+1)/2; k++ ) { while( j & N-k ) s[i][j++] = a++; i++; j--; while( i & N-k ) s[i++][j] = a++; i--; j--; while( j & k-1 ) s[i][j--] = a++; i--; j++; while( i & k ) s[i--][j] = a++; i++; j++; } for( i = 0; i & N; i++ ) { for( j = 0; j & N; j++ ) cout && s[i][j] && '\t'; cout && } } 2 define MAX_N 100 int matrix[MAX_N][MAX_N]; /* *(x,y):第一个元素的坐标 * start:第一个元素的值 * n:矩阵的大小 */ void SetMatrix(int x, int y, int start, int n) { int i, if (n &= 0) //递归结束条件 if (n == 1) { //矩阵大小为 1 时 matrix[x][y] = } for (i = i & x + n-1; i++) //矩阵上部 matrix[y][i] = start++; for (j = j & y + n-1; j++) //右部 matrix[j][x+n-1] = start++; for (i = x+n-1; i & i--) //底部 matrix[y+n-1][i] = start++; for (j = y+n-1; j & j--) matrix[j][x] = start++; } void main() { int i, scanf(&%d&, &n); SetMatrix(0, 0, 1, n); //打印螺旋矩阵 for(i = 0; i & i++) { for (j = 0; j & j++) printf(&%4d&, matrix[i][j]); printf(&\n&); } } 斐波拉契数列递归实现的方法如下: int Funct( int n ) { if(n==0) return 1; if(n==1) return 1; retrurn Funct(n-1) + Funct(n-2); } 请问,如何不使用递归,来实现上述函数? 请教各位高手! 解答:int Funct( int n ) // n 为非负整数 { int a=0; int b=1; if(n==0) c=1; else if(n==1) c=1; else for(int i=2;i&=n;i++) //应该 n 从 2 开始算起 { c=a+b; a=b; //左部 //递归SetMatrix(x+1, y+1, start, n-2); b=c; } } 解答: 现在大多数系统都是将低字位放在前面,而结构体中位域的申明一般是先声明高位。 100 的二进制是 001 100 100 低位在前 高位在后 001----s3 100----s2 100----s1 所以结果应该是 1 如果先申明的在低位则: 001----s1 100----s2 100----s3 结果是 4 1、原题跟 little-endian,big-endian 没有关系 2、原题跟位域的存储空间分配有关,到底是从低字节分配还是从高字节分配,从 Dev C++ 和 VC7.1 上看,都是从低字节开始分配,并且连续分配,中间不空,不像谭的书那样会留空 位 3、原题跟编译器有关,编译器在未用堆栈空间的默认值分配上有所不同,Dev C++未用空 间分配为 b,VC7.1 下为 b,所以在 Dev C++下的结果为 5,在 VC7.1 下为 1。 注:PC 一般采用 little-endian,即高高低低,但在网络传输上,一般采用 big-endian,即高低 低高,华为是做网络的,所以可能考虑 big-endian 模式,这样输出结果可能为 4 判断一个字符串是不是回文 int IsReverseStr(char *aStr) { int i,j; int found=1; if(aStr==NULL) return -1; j=strlen(aStr); for(i=0;i&j/2;i++) if(*(aStr+i)!=*(aStr+j-i-1)) { found=0; } }Josephu 问题为:设编号为 1,2,… n 的 n 个人围坐一圈,约定编号为 k(1&=k&=n)的人 从 1 开始报数,数到 m 的那个人出列,它的下一位又从 1 开始报数,数到 m 的那个人又出 列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。 数组实现: #include &stdio.h& #include &malloc.h& int Josephu(int n, int m) { int flag, i, j = 0; int *arr = (int *)malloc(n * sizeof(int)); for (i = 0; i & ++i) arr[i] = 1; for (i = 1; i & ++i) { flag = 0; while (flag & m) { if (j == n) j = 0; if (arr[j]) ++ ++j; } arr[j - 1] = 0; printf(&第%4d 个出局的人是:%4d 号\n&, i, j); } free(arr); } int main() { int n, scanf(&%d%d&, &n, &m); printf(&最后胜利的是%d 号!\n&, Josephu(n, m)); system(&pause&); return 0; } 链表实现: #include &stdio.h& #include &malloc.h& typedef struct Node { struct Node * }JosephuN int Josephu(int n, int m) { int i, JosephuNode *head, * head = tail = (JosephuNode *)malloc(sizeof(JosephuNode)); for (i = 1; i & ++i) { tail-&index = tail-&next = (JosephuNode *)malloc(sizeof(JosephuNode)); tail = tail-& } tail-&index = tail-&next = for (i = 1; tail != ++i) { for (j = 1; j & ++j) { tail = head = head-& } tail-&next = head-& printf(&第%4d 个出局的人是:%4d 号\n&, i, head-&index); free(head); head = tail-& } i = head-& free(head); } int main() { int n, scanf(&%d%d&, &n, &m); printf(&最后胜利的是%d 号!\n&, Josephu(n, m)); system(&pause&); return 0; } 已知 strcpy 函数的原型是: char * strcpy(char * strDest,const char * strSrc); 1.不调用库函数,实现 strcpy 函数。 2.解释为什么要返回 char *。 解说: 1.strcpy 的实现代码 char * strcpy(char * strDest,const char * strSrc) { if ((strDest==NULL)||(strSrc==NULL)) file://[/1] throw &Invalid argument(s)&; //[2] char * strDestCopy=strD file://[/3] while ((*strDest++=*strSrc++)!='\0'); file://[/4] return strDestC } 错误的做法: [1] (A)不检查指针的有效性,说明答题者不注重代码的健壮性。 (B)检查指针的有效性时使用((!strDest)||(!strSrc))或(!(strDest&&strSrc)),说明答题者 对 C 语言中类型的隐式转换没有深刻认识。在本例中 char *转换为 bool 即是类型隐式转换,这种 功能虽然灵活,但更多的是导致出错概率增大和维护成本升高。所以 C++专门增加了 bool、 true、false 三个关键字以提供更安全的条件表达式。 (C)检查指针的有效性时使用((strDest==0)||(strSrc==0)),说明答题者不知道使用常量的好 处。直接使用字面常量(如本例中的 0)会减少程序的可维护性。0 虽然简单,但程序中可 能出现很多处对指针的检查,万一出现笔误,编译器不能发现,生成的程序内含逻辑错误, 很难排除。而使用 NULL 代替 0,如果出现拼写错误,编译器就会检查出来。 [2] (A)return new string(&Invalid argument(s)&);,说明答题者根本不知道返回值的用途,并且他 对内存泄漏也没有警惕心。从函数中返回函数体内分配的内存是十分危险的做法,他 把释 放内存的义务抛给不知情的调用者,绝大多数情况下,调用者不会释放内存,这导致内存泄 漏。 (B)return 0;,说明答题者没有掌握异常机制。调用者有可能忘记检查返回值,调用者还可 能无法检查返回值(见后面的链式表达式)。妄想让返回值肩负返回正确值和异常 值的双 重功能,其结果往往是两种功能都失效。应该以抛出异常来代替返回值,这样可以减轻调用 者的负担、使错误不会被忽略、增强程序的可维护性。 [3] (A)忘记保存原始的 strDest 值,说明答题者逻辑思维不严密。 [4] (A)循环写成 while (*strDest++=*strSrc++);,同[1](B)。 (B)循环写成 while (*strSrc!='\0') *strDest++=*strSrc++;,说明答题者对边界条件的检查不 力。循环体结束后,strDest 字符串的末尾没有正确地加上'\0'。c/c++笔试题目(林锐)本试题仅用于考查 C++/C 程序员的基本编程技能。内容限于 C++/C 常用语法,不涉及数据 结构、算法以及深奥的语法。考试成绩能反映出考生的编程质量以及对 C++/C 的理解程 度,但不能反映考生的智力和软件开发能力。 笔试时间 90 分钟。请考生认真答题,切勿轻视。 一、请填写 BOOL , float, 指针变量 与“零值”比较的 if 语句。(10 分) 提示:这里“零值”可以是 0, 0.0 , FALSE 或者“空指针”。例如 int 变量 n 与“零值”比较的 if 语句为: if ( n == 0 ) if ( n != 0 ) 以此类推。请写出 BOOL flag 与“零值”比较的 if 语句:请写出 float x 与“零值”比较的 if 语句:请写出 char *p 与“零值”比较的 if 语句:二、以下为 Windows NT 下的 32 位 C++程序,请计算 sizeof 的值(10 分) char str[] = “Hello” ; char *p = int n = 10; 请计算 sizeof (str ) = sizeof ( p ) = sizeof ( n ) = void Func ( char str[100]) { 请计算 sizeof( str ) = } void *p = malloc( 100 ); 请计算 sizeof ( p ) = 三、简答题(25 分) 1、头文件中的 ifndef/define/endif 干什么用? 2、#include &filename.h& 和 #include “filename.h” 有什么区别?3、const 有什么用途?(请至少说明两种) 4、在 C++ 程序中调用被 C 编译器编译后的函数,为什么要加 extern “C”声明?5、请简述以下两个 for 循环的优缺点 // 第一个 for (i=0; i&N; i++) { if (condition) DoSomething(); else DoOtherthing(); } // 第二个 if (condition) { for (i=0; i&N; i++) DoSomething(); } else { for (i=0; i&N; i++) DoOtherthing(); } 优点: 缺点: 优点: 缺点:四、有关内存的思考题(20 分) void GetMemory(char *p) { p = (char *)malloc(100); } void Test(void) { char *str = NULL; GetMemory(str); strcpy(str, &hello world&); printf(str); } 请问运行 Test 函数会有什么样的结果? 答: char *GetMemory(void) { char p[] = &hello world&; } void Test(void) { char *str = NULL; str = GetMemory(); printf(str); } 请问运行 Test 函数会有什么样的结果? 答:Void GetMemory2(char **p, int num) { *p = (char *)malloc(num); } void Test(void) { char *str = NULL; GetMemory(&str, 100); strcpy(str, &hello&); printf(str); } 请问运行 Test 函数会有什么样的结果? 答: void Test(void) { char *str = (char *) malloc(100); strcpy(str, “hello”); free(str); if(str != NULL) { strcpy(str, “world”); printf(str); } } 请问运行 Test 函数会有什么样的结果? 答: 五、编写 strcpy 函数(10 分) 已知 strcpy 函数的原型是 char *strcpy(char *strDest, const char *strSrc); 其中 strDest 是目的字符串,strSrc 是源字符串。 (1)不调用 C++/C 的字符串库函数,请编写函数 strcpy(2)strcpy 能把 strSrc 的内容复制到 strDest,为什么还要 char * 类型的返回值?六、编写类 String 的构造函数、析构函数和赋值函数(25 分) 已知类 String 的原型为: class String { public: String(const char *str = NULL); // 普通构造函数 String(const String &other); // 拷贝构造函数 ~ String(void); // 析构函数 String & operate =(const String &other); // 赋值函数 private: char *m_ // 用于保存字符串 }; 请编写 String 的上述 4 个函数。 顽主 评论于
22:27 # re: c++面试题 回复 附录 C :C++/C 试题的答案与评分标准 一、请填写 BOOL , float, 指针变量 与“零值”比较的 if 语句。(10 分) 请写出 BOOL flag 与“零值”比较的 if 语句。(3 分) 标准答案: if ( flag ) if ( !flag ) 如下写法均属不良风格,不得分。 if (flag == TRUE) if (flag == 1 ) if (flag == FALSE) if (flag == 0) 请写出 float x 与“零值”比较的 if 语句。(4 分) 标准答案示例: const float EPSINON = 0.00001; if ((x &= - EPSINON) && (x &= EPSINON) 不可将浮点变量用“==”或“!=”与数字比较,应该设法转化成“&=”或“&=”此类形式。 如下是错误的写法,不得分。 if (x == 0.0) if (x != 0.0) 请写出 char *p 与“零值”比较的 if 语句。(3 分) 标准答案: if (p == NULL) if (p != NULL) 如下写法均属不良风格,不得分。 if (p == 0) if (p != 0) if (p) if (!) 二、以下为 Windows NT 下的 32 位 C++程序,请计算 sizeof 的值(10 分) char str[] = “Hello” ; char *p = int n = 10; 请计算 sizeof (str ) = 6 (2 分) sizeof ( p ) = 4 (2 分) sizeof ( n ) = 4 (2 分) void Func ( char str[100]) { 请计算 sizeof( str ) = 4 (2 分) } void *p = malloc( 100 ); 请计算 sizeof ( p ) = 4 (2 分)三、简答题(25 分) 1、头文件中的 ifndef/define/endif 干什么用?(5 分) 答:防止该头文件被重复引用。 2、#include &filename.h& 和 #include “filename.h” 有什么区别?(5 分) 答:对于#include &filename.h& ,编译器从标准库路径开始搜索 filename.h 对于#include “filename.h” ,编译器从用户的工作路径开始搜索 filename.h 3、const 有什么用途?(请至少说明两种)(5 分) 答:(1)可以定义 const 常量 (2)const 可以修饰函数的参数、返回值,甚至函数的定义体。被 const 修饰的东西都受到 强制保护,可以预防意外的变动,能提高程序的健壮性。 4、在 C++ 程序中调用被 C 编译器编译后的函数,为什么要加 extern “C”? (5 分) 答:C++语言支持函数重载,C 语言不支持函数重载。函数被 C++编译后在库中的名字与 C 语言的不同。假设某个函数的原型为: void foo(int x, int y); 该函数被 C 编译器编译后在库 中的名字为_foo,而 C++编译器则会产生像_foo_int_int 之类的名字。 C++提供了 C 连接交 换指定符号 extern“C”来解决名字匹配问题。 5、请简述以下两个 for 循环的优缺点(5 分) for (i=0; i&N; i++) { if (condition) DoSomething(); else DoOtherthing(); } if (condition) { for (i=0; i&N; i++) DoSomething(); } else { for (i=0; i&N; i++) DoOtherthing(); } 优点:程序简洁 缺点:多执行了 N-1 次逻辑判断,并且打断了循环“流水线”作业,使得编译器不能对循环进 行优化处理,降低了效率。 优点:循环的效率高 缺点:程序不简洁 四、有关内存的思考题(每小题 5 分,共 20 分) void GetMemory(char *p) { p = (char *)malloc(100); } void Test(void) { char *str = NULL; GetMemory(str); strcpy(str, &hello world&); printf(str); } 请问运行 Test 函数会有什么样的结果? 答:程序崩溃。因为 GetMemory 并不能 传递动态内存, Test 函数中的 str 一 直都是 NULL。 strcpy(str, &hello world&); 将使程序崩溃。 char *GetMemory(void) { char p[] = &hello world&; } void Test(void) { char *str = NULL; str = GetMemory(); printf(str); } 请问运行 Test 函数会有什么样的结果? 答:可能是乱码。 因为 GetMemory 返回的 是指向“栈内存”的指针,该指针的地址 不是 NULL,但其原现的内容已经被清 除,新内容不可知。 void GetMemory2(char **p, int num) { *p = (char *)malloc(num); } void Test(void) { char *str = NULL; GetMemory(&str, 100); strcpy(str, &hello

我要回帖

更多关于 ios 数组越界防止崩溃 的文章

 

随机推荐