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,因为还有'\0',函数内的str实际只是一个指向字符串的指针,没有任何额外的与数组相关的信息,因此sizeof作用于上只将其当指针看,一个指针为4个字节,因此返回4。
5.
一个32位的机器,该机器的指针是多少位
答:指针是多少位只要看地址总线的位数就行了。80386以后的机子都是32的数据总线。所以指针的位数就是4个字节了。
6.
main()
{
int a[5]={1,2,3,4,5};
int *ptr=(int *)(&a+1);
printf("%d,%d\n",*(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]。
7. 请问以下代码有什么问题?
char a;
char *str=&a;
strcpy(str,"hello");
printf(str);
答:没有为str分配内存空间,将会发生异常。问题出在将一个字符串复制进一个字符变量指针所指地址。虽然可以正确输出结果,但因为越界进行内在读写而导致程序崩溃。
8.
char* s="aaa";
printf("%s",s);
s[0]='b';
printf("%s",s);
有什么问题?
答:"aaa"是字符串常量。s是指针,指向这个字符串常量,所以声明s的时候就有问题。
cosnt char* s="aaa"; 然后又因为是常量,所以对是s[0]的赋值操作是不合法的。
9. 写一个“标准”宏,这个宏输入两个参数并返回较小的一个。
答:#define min(x, y) ((x)>(y)?(y)x)) //结尾没有';'
10. 嵌入式系统中经常要用到无限循环,你怎么用c编写死循环。
答:while(1){}或者for(;;)
11. 关键字static的作用是什么?
答:定义静态变量
12. 关键字const有什么含意?
答:表示常量不可以修改的变量。
13. 关键字volatile有什么含意?并举出三个不同的例子?
答:提示编译器对象的值可能在编译器未监测到的情况下改变。
14. int (*s[10])(int) 表示的是什么啊?
答:int (*s[10])(int) 函数指针数组,每个指针指向一个int func(int param)的函数。
15. 请问下列表达式哪些会被编译器禁止?为什么?
int a=248;
b=4;
int const c=21;
const int *d=&a;
int *const e=&b;
int const *f const =&a;
答:
b=4; => int b=4;
int const *f const=&a; => int const *const f=&a;
16.
交换两个变量的值,不使用第三个变量。即a=3,b=5,交换之后a=5,b=3;
答:有两种解法, 一种用算术算法, 一种用^(异或)
a = a + b;
b = a - b;
a = a - b;
or
a = a^b;// 只能对int,char..
b = a^b;
a = a^b;
or
a ^= b ^= a;
17.有什么问题
#include
#include
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操作很危险
18. 列举几种进程的同步机制,并比较其优缺点。
答:原子操作、信号量机制、自旋锁、管程、会合、分布式系统
20. 进程之间通信的途径
答:共享存储系统、消息传递系统、管道:以文件系统为基础
21. 进程死锁的原因和4个必要条件
答:资源竞争及进程推进顺序非法;互斥、请求保持、不可剥夺、环路
22. 死锁的处理
答:鸵鸟策略、预防策略、避免策略、检测与解除死锁
23. 操作系统中进程调度策略有哪几种?
答:fcfs(先来先服务),优先级,时间片轮转,多级反馈
24. 类的静态成员和非静态成员有何区别?
答:类的静态成员每个类只有一个,非静态成员每个对象一个
25. 纯虚函数如何定义?使用时应注意什么?
答:virtual void f()=0; 是接口,子类必须要实现
26. 数组和链表的区别
答:
数组:数据顺序存储,固定大小
链表:数据可以随机存储,大小可动态改变
27. iso的七层模型是什么?tcp/udp是属于哪一层?tcp/udp有何优缺点?
答:应用层、表示层、会话层、传输层、网络层、物理链路层、物理层
tcp/udp属于运输层
tcp服务提供了数据流传输、可靠性、有效流控制、全双工操作和多路复用技术等。
与tcp 不同, udp并不提供对ip协议的可靠机制、流控制以及错误恢复功能等。由于udp比较简单,udp头包含很少的字节,比tcp负载消耗少
tcp: 提供稳定的传输服务,有流量控制,缺点是包头大,冗余性不好
udp: 不提供稳定的服务,包头小,开销小
28. (void *)ptr 和 (*(void**))ptr的结果是否相同?其中ptr为同一个指针
答:(void *)ptr 和 (*(void**))ptr值是相同的
29.
int main()
{
int x=3;
printf("%d",x);
return 1;
}
问函数既然不会被其它函数调用,为什么要返回1?
答:main中,c标准认为0表示成功,非0表示错误。具体的值是某中具体出错信息
30. 要对绝对地址0x100000赋值,我们可以用(unsigned int*)0x100000 = 1234; 那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做?
答:*((void (*)( ))0x100000 ) ( );
首先要将0x100000强制转换成函数指针,即: (void (*)())0x100000。然后再调用它: *((void (*)())0x100000)(); 用typedef可以看得更直观些:
typedef void(*)() voidfuncptr;
*((voidfuncptr)0x100000)();
31. 已知一个数组table,用一个宏定义,求出数据的元素个数
答:
#define ntbl
#define ntbl (sizeof(table)/sizeof(table[0]))
32. 线程与进程的区别和联系? 线程是否具有相同的堆栈? dll是否有独立的堆栈?
答:进程是死的,只是一些资源的集合,真正的程序执行都是线程来完成的,程序启动的时候操作系统就帮你创建了一个主线程。每个线程有自己的堆栈。dll中有没有独立的堆栈,这个问题不好回答,或者说这个问题本身是否有问题。因为dll中的代码是被某些线程所执行,只有线程拥有堆栈,如果dll中的代码是exe中的线程所调用,那么这个时候是不是说这个dll没有自己独立的堆栈?如果dll中的代码是由dll自己创建的线程所执行,那么是不是说dll有独立的堆栈?
以上讲的是堆栈,如果对于堆来说,每个dll有自己的堆,所以如果是从dll中动态分配的内存,最好是从dll中删除,如果你从dll中分配内存,然后在exe中,或者另外一个dll中删除,很有可能导致程序崩溃
33.
unsigned short a = 10;
printf("~a = %u\n", ~a);
char c=128;
printf("c = %d\n",c);
输出多少?并分析过程
答:
第一题,~a =0xfffffff5, int值为-11,但输出的是uint。所以输出4294967285。
第二题,c=0x10,输出的是int,最高位为1,是负数,所以它的值就是0x00的补码就是128,所以输出-128。
这两道题都是在考察二进制向int或uint转换时的最高位处理。
(二) 中级题
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)
2. 用两个栈实现一个队列的功能?要求给出算法和思路!
答:设2个栈为a,b, 一开始均为空.
入队:
将新元素push入栈a;
出队:
(1)判断栈b是否为空;
(2)如果不为空,则将栈a中所有元素依次pop出并push到栈b;
(3)将栈b的栈顶元素pop出;
这样实现的队列入队和出队的平摊复杂度都还是o(1), 比上面的几种方法要好。
3. 在c语言库函数中将一个字符转换成整型的函数是atol()吗,这个函数的原型是什么?
答:
函数名: 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);
}
4. 对于一个频繁使用的短小函数,在c语言中应用什么实现,在c++中应用什么实现?
答:c用宏定义,c++用inline
5. 直接链接两个信令点的一组链路称作什么?
答:ppp点到点连接
7. 软件测试都有那些种类?
答:黑盒:针对系统功能的测试 白合:测试函数功能,各函数接口
8. 确定模块的功能和模块的接口是在软件设计的那个阶段完成的?
答:概要设计阶段
9.
unsigned char *p1;
unsigned long *p2;
p1=(unsigned char *)0x801000;
p2=(unsigned long *)0x810000;
请问
p1+5=______;
p2+5=______;
答案:801005;810014。不要忘记了这个是16进制的数字,p2要加20变为16进制就是14
选择题:
1. ethternet链接到internet用到以下那个协议?
a.hdlc; b.arp; c.udp; d.tcp; e.ip
2. 属于网络层协议的是:
a.tcp; b.ip; c.icmp; d.x.25
答:b,c
3.windows消息调度机制是:
a.指令队列; b.指令堆栈; c.消息队列; d.消息堆栈;
答:b,a,c
找错题:
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 square(a) ((a)*(a))
int a=5;
int b;
b=square(a++);
答案:这个没有问题,s(a++),就是((a++)×(a++))唯一要注意的就是计算后a=7了
3. 找错误
typedef unsigned char byte
int examply_fun(byte gt_len; byte *gt_code)
{
byte *gt_buf;
gt_buf=(byte *)malloc(max_gt_length);
if(gt_len>max_gt_length)
{
return gt_length_error;
}
}
答:要释放内存
问答题:
1.ip phone的原理是什么?
答:ipv6
2.tcp/ip通信建立的过程怎样,端口有什么作用?
答:三次握手,确定是哪个应用程序使用该协议
(三) 高级题
1、static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?
答:全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。
而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用, 因此可以避免在其它源文件中引起错误。从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域, 限制了它的使用范围。
static函数与普通函数作用域不同。仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件
static全局变量与普通的全局变量有什么区别:static全局变量只初使化一次,防止在其他文件单元中被引用;
static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依据上一次结果值;
static函数与普通函数有什么区别:static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝
2、程序的局部变量存在于()中,全局变量存在于()中,动态申请数据存在于()中。
答:栈;静态区;堆
3、设有以下说明和定义:
typedef union {long i; int k[5]; char c;} date;
struct data { int cat; date cow; double dog;} too;
date max;
则语句printf("%d",sizeof(too)+sizeof(max));的执行结果是:______
答:date是一个union, 变量公用空间. 里面最大的变量类型是int[5], 占用20个字节. 所以它的大小是20
data是一个struct, 每个变量分开占用空间. 依次为int4 + date20 + double8 = 32.
所以结果是 20 + 32 = 52.
当然...在某些16位编辑器下, int可能是2字节,那么结果是 int2 + date10 + double8 = 20
4、队列和栈有什么区别?
答:队列先进先出,栈后进先出÷
5、已知一个单向链表的头,请写出删除其某一个结点的算法,要求,先找到此结点,然后删除。
答:
slnodetype *delete(slnodetype *head,int key)
{
if(head->number==key)
{
head=pointer->next;
free(pointer);
break;
}
back = pointer;
pointer=pointer->next;
if(pointer->number==key)
{
back->next=pointer->next;
free(pointer);
break;
}
void delete(node* p)
{
if(head = node)
while(p)
}
}
7、请找出下面代码中的所有错误
说明:以下代码是把一个字符串倒序,如“abcd”倒序后变为“dcba”
#include "string.h"
main()
{
char *src="hello,world";
char* dest=null;
int len=strlen(src);
dest=(char*)malloc(len);
char* d=dest;
char* s=src[len];
while(len--!=0)
d++=s--;
printf("%s",dest);
return 0;
}
答:还要加上#include
int main()
{
char* src = "hello,world";
int len = strlen(src);
char* dest = (char*)malloc((len+1)*sizeof(char)); //要为\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;
}
高质量C++编程指南:
1,零值比较
if(n==0) if(n!=0)
if(!flag) if(flag)
if((abs(x-0))<0.00000001) if((abs(x-0))>0.00000001)
if(p==NULL) if(p!=NULL)
2,
char str[]="hello";
char *p=str;
int n=10;
sizeof(str)=6
sizeof(p)=4
sizeof(n)=4
vod Func(char str[100]){
sizeof(str)=4
}
void *p=malloc(100);
sizeof(p)=4
4,
void test(int x,int y)
C编译后符号库中名字为_test,而C++编译器产生像_test_int_int之类的名字。
四、
hello worldasdfasdfsdfasdfasdf
hello world
函数不可返回指向栈内存的指针或引用,该内存在函数结束时被自动摧毁。
char *Func(void){
char str[] = "hello world";//str的内存位于栈内
...
return str;
}
使用return temp(s1+s2),而不用
string temp(s1+s2)
return temp
函数不要带有记忆功能,相同输入应产生相同输出。
static局部变量是函数的记忆存储器,尽量少用static局部变量。
断言asset是仅在debug版本起作用的宏。
数组内容复制和比较
数组,不能用b=a复制,b==a比较,使用strcpy复制,使用strcmp比较
指针,不能用p=a复制,p==a比较,使用strcpy复制,使用strcmp
比较
数组作为函数参数传递时,数组自动退化为同类型的指针
函数参数是一个指针,不要指望用指针去申请动态内存
malloc/free是C语言标准库函数,new/delete是C++的运算符。不能把执行构造函数和析构函数的任务强加于malloc/free。
重载:同一类,名字相同,参数不同
覆盖:父子类,名字相同,参数相同,有virtual
1)父子类,名字相同,参数不同,基类函数被隐藏。(非重载)区别在于同一类还是父子类。
2)父子类,名字相同,参数相同,基类函数无virtual,基类函数被隐藏。(非覆盖)区别在于是否有virtual。
参数缺省值出现在函数的声明中,不能出现在函数的定义体中。
inline必须与函数定义体放在一起才能使函数成为内联。仅将inline放在函数声明前不起作用。
声明和定义不可混为一谈,用户没有必要,也不应该知道函数是否需要内联。
定义数组的同时必须初始化数组,使用free或delete释放内存后,没有将指针设置为NULL,产生野指针。
解决:对象初始化工作放在构造函数中,清除工作放在析构函数中。当对象被创建时,构造函数自动执行,当对象消亡时,析构函数自动执行。
这样就不用担心对象的初始化和清除工作。
构造函数初始化表执行发生在函数体内的任何代码执行之前。
1,类存在继承关系,派生类必须在初始化表里调用基类的构造函数。
2,类的const变量只能在初始化表里被初始化,因为它不能在函数体内用赋值的方式初始化。
3,非内部数据成员对象应当采用初始化表方式初始化,以获取更高的效率。
对于内部数据类型的数据成员而言,两种初始化方式的效率几乎一样,建议用构造函数体内赋值的方式。
成员对象初始化的次序完全不受在初始化表中次序的影响,由在类中声明的次序决定。
拷贝构造函数与赋值函数
如果不主动编写拷贝构造函数和赋值函数,编译器以位拷贝的方式自动生成缺省函数。如类中含有指针,2个缺省将隐含着错误。
拷贝构造函数是在对象被创建时调用,赋值函数只能被已经存在的对象调用。
string a("hello");
string a("world");
string c=a;//拷贝构造函数
c=a;//赋值函数
派生类的构造函数应在初始化表里调用基类的构造函数
基类与派生类的析构函数应该为虚。
编写派生类赋值函数时,也要对基类数据成员重新赋值。
Base::operate =(other);
constructor destructor assignment
const constant
输入参数采用值传递,函数将自动产生临时变量用于复制参数,输入参数无需保护,不要加const。
void Func1(int x)不要写为void Func1(const int x)
void Func2(A a)不要写为void Func2(const A a),形参要赋值对象A,函数效率低
传引用void Func3(B &b)要写为void Func3(const B &b)
对于非内部数据类型输入参数,应该将值传递方式改为const引用传递,提高执行效率。
对于内部数据类型的输入参数,不要将值传递该为const引用传递,不会提高效率。
程序效率
时间效率指执行速度,空间效率指占用内存或外存状况。
紧凑的代码未必产生高效的机器码。
尽量使用显示数据类型初始化,避免让编译器进行隐式数据类型转换。
指针传递方式,函数返回值加const修饰,函数返回值内容不能被修改。
const char* getString(void);//返回指针不能被修改
const char *str=getString();//返回指针赋值为const类型指针
值传递方式,函数会把返回值复制到外部临时存储单元,加const无任何意义。
const成员函数,任何不修改数据成员的函数都应声明为const类型。const放在函数最后。
int getCount(void) const;//const成员函数
void getMemory(char *p, int num)
{
p=(char *)malloc(sizeof(char)*num);
}
void test(void)
{
char *str=NULL;
getMemory(str,100);//str仍然为NULL
strcpy(str,"hello");//运行错误
}
编译器为每个函数参数制作一个副本,指针参数p的副本是_p,编译器使_p=p,
如果函数体内的程序修改了_p的内容,导致参数p的内容作相应修改。这即是指针用作输出参数的原因。
本例中,_p申请了新内存,只是把_p所指的内存地址改变了,但是p丝毫未变。
char *getString(void)
{
char p[]="hello world";
return p;
}
void test4(void)
{
char *str=NULL;
str=getString();//str的内容是垃圾
cout<
}
return语句返回栈内存,栈内存在函数返回时自动消亡。
char *getMemory3(int num)
{
char *p=(char *)malloc(sizeof(char)*num);
return p;
}
void test3(void)
{
char *str=NULL;
str=getMemory3(100);
strcpy(str,"hello");
cout<
free(str);
}
char *p=(char *)malloc(100);
strcpy(p,"hello");
free(p);
if(p!=NULL)
{
strcpy(p,"world");//出错
}
char *getString2(void){
char *p ="hello world";
return p}
void test5(void){
char *str=NULL;
str=getString2();
cout<
}
C++问答:
1,vc6.0中无法使用cout输出string类型变量的解决办法 http://hi.baidu.com/ruisen/blog/item/6f157b435a2c97129213c66b.html
答:vc6.0中无法使用cout输出string类型变量的解决办法:
其实,这个问题的出现完全是应为你自己不老实。在多数的教程上会教你用
#include
#include
但你若使用了
#include
#include
的话,问题就会出现了。至于为什么,我也不是很清楚,大家可以查看CSDN中的帮助:
http://blog.csdn.net/gengxt2003/archive/2007/06/07/1642236.aspx
这个问题对我们这些新手来说可能是十分头痛的,但如果你按照教程上的方法来编写代码的话也许就不会出现这个问题了。虽然大家不一定都会遇到,但发出来还是希望对那些遇到了这个问题的朋友有所帮助。
2,CString,int,string,char*之间的转换 http://hi.baidu.com/tiemsn/blog/item/f5ff86d6eae1602e06088b71.html
1 CString,int,string,char*之间的转换
string 转 CString
CString.format("%s", string.c_str());
char 转 CString
CString.format("%s", char*);
char 转 string
string s(char *);
string 转 char *
char *p = string.c_str();
CString 转 string
string s(CString.GetBuffer());
1,string -> CString
CString.format("%s", string.c_str());
用c_str()确实比data()要好.
2,char -> string
string s(char *);
你的只能初始化,在不是初始化的地方最好还是用assign().
3,CString -> string
string s(CString.GetBuffer());
GetBuffer()后一定要ReleaseBuffer(),否则就没有释放缓冲区所占的空间.
《C++标准函数库》中说的
有三个函数可以将字符串的内容转换为字符数组和C—string
1.data(),返回没有”\0“的字符串数组
2,c_str(),返回有”\0“的字符串数组
3,copy()
CString互转int
将字符转换为整数,可以使用atoi、_atoi64或atol。
而将数字转换为CString变量,可以使用CString的Format函数。如
CString s;
int i = 64;
s.Format("%d", i)
Format函数的功能很强,值得你研究一下。
void CStrDlg::OnButton1()
{
// TODO: Add your control notification handler code here
CString
ss="1212.12";
int temp=atoi(ss);
CString aa;
aa.Format("%d",temp);
AfxMessageBox("var is " + aa);
}
sart.Format("%s",buf);
CString互转char*
///char * TO cstring
CString strtest;
char * charpoint;
charpoint="give string a value";
strtest=charpoint;
///cstring TO char *
charpoint=strtest.GetBuffer(strtest.GetLength());
标准C里没有string,char *==char []==string
可以用CString.Format("%s",char *)这个方法来将char *转成CString。要把CString转成char *,用操作符(LPCSTR)CString就可以了。
CString转换 char[100]
char a[100];
CString str("aaaaaa");
strncpy(a,(LPCTSTR)str,sizeof(a));
2 CString类型的转换成int
CString类型的转换成int
将字符转换为整数,可以使用atoi、_atoi64或atol。
//CString aaa = "16" ;
//int int_chage = atoi((lpcstr)aaa) ;
而将数字转换为CString变量,可以使用CString的Format函数。如
CString s;
int i = 64;
s.Format("%d", i)
Format函数的功能很强,值得你研究一下。
如果是使用char数组,也可以使用sprintf函数。
//CString ss="1212.12";
//int temp=atoi(ss);
//CString aa;
//aa.Format("%d",temp);
数字->字符串除了用CString::Format,还有FormatV、sprintf和不需要借助于Afx的itoa
3 char* 在装int
#include
int atoi(const char *nptr);
long atol(const char *nptr);
long long atoll(const char *nptr);
long long atoq(const char *nptr);
4 CString,int,string,char*之间的转换
string aa("aaa");
char *c=aa.c_str();
cannot convert from 'const char *' to 'char *'
const char *c=aa.c_str();
5 CString,int,string,char*之间的转换
string.c_str()只能转换成const char *,
要转成char *这样写:
string mngName;
char t[200]; memset(t,0,200); strcpy(t,mngName.c_str());
ESP,Embeded Systems Programming C语言
预处理器Preprocessor
1,预处理指令声明一个常量
#define SECONDS_PER_YEARS (60*60*24*365)UL
2,写一个标准宏MIN,输入2个参数返回最小值
#define MIN ((A)<=(B)?(A):(B))
3,死循环Infinite loops
while(1){}
或者
Loop:
go Loop;
4,数据声明Data declarations
int a;//An integer
int *a;//A pointer to an integer
int **a;//A pointer to a pointer to an integer
int a[10];//An array of 10 integers
int *a[10];//An array of 10 pointers to integers
int (*a)[10];//A pointer to an array of 10 integers
int (*a)(int);//A pointer to a function a that takes an integer argument and returns an integer
int (*a[10])(int);//An array of 10 pointers to functions that take an integer argument and return an integer
5,Static
1)函数体内,声明为static的变量,在函数被调用过程中其值保持不变
2)函数体外,模块内,声明为static的变量可以被模块内所有函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。
3)函数体外,模块内,声明为static的函数只可被这个模块内的其它函数调用。这个函数被限制在声明它的模块的本地范围内使用。
6,Const
意味着只读。
const int a;//常整形数
int const a;//常整形数
const int *a;//指向常整数的指针。整型数不可修改,指针可修改
int * const a;//指向整型数的常指针。整型数可以修改,指针不可修改
int const * a const;//指向常整型数的常指针。指针指向的整型数不可修改,指针不可修改
7,Volatile
意味着变量会被意想不到地改变。这样,优化器用到这个变量时必须每次都小心地重新读取这个变量的值。
几个典型应用场景:
1)并行设备的硬件寄存器
2)中断服务子程序会访问到的非自动变量
3)多线程应用中被几个任务共享的变量
问题:
1)一个参数既可以使const还可以是volatile吗?
2)一个指针可以是volatile吗?
3)下面函数有什么错误?
int square (volatile int *ptr){
return *ptr * *ptr;
}
答案:
1)是的。只读状态寄存器,volatile因为它可能被意想不到地改变。const因为程序不应该试图修改它。
2)是的。
3)正确代码。
int square (volatile int *ptr){
int a;
a=*ptr;
return a*a;
}
8,位操作Bit manipulation
11,代码例子Code examples
void foo(void){
unsigned int a=6;
int b=-20;
(a+b>6)puts(">6"):puts("<=6")
}
答案:>6。存在有符号整型和无符号整型时,所有的操作数都自动转换为无符号整型。
14,Typedef
声明一个已经存在的数据类型的同义词。可以用预处理器做类似的事。那种方法更好呢?
#define dPS struct s *
typedef struct s * tPS;
dPS p1,p2;
tPS p3,p4;
第一个扩展为:
struct s * p1,p2;
p1为指向结构的指针,p2为一个实际的结构。第二个例子正确定义p3和p4两个指针。typedef更好。
15,晦涩的语法
int a=5,b=7,c;
c=a+++b;
根据最处理原则,编译器应当能处理尽可能所有合法的用法。理解为:c=a++ + b;运行后a=6,b=7,c=12。
16,什么是引用,声明和使用引用要注意什么?
引用是某个目标变量的别名alias,对引用操作和直接对变量操作完全相同。声明引用时要对其进行初始化。引用声明完成相当于目标变量有2个名称,不能将引用名作为其他变量名的别名。本身不是一种数据类型,引用本身不占存储单元。
17,引用作为函数参数有哪些特点?
1)传递引用给函数与传递指针的效果是一样的。被调函数中对形参变量的操作就是对其相应的目标对象的操作。
2)引用传递函数的参数,内存中没有产生实参的副本,是直接对实参操作;一般变量传递函数参数,发生函数调用时,需要给形参分配存储单元,形参变量 是实参变量的副本。如果传递的是对象,还调用拷贝构造函数。当参数传递的数据较大时,引用比用一般变量传递参数的效率和所占空间都好。
3)使用指针作为函数参数也能得到使用引用的效果。但被调函数中同样要给形参分配存储单元;主调函数的调用点处,必须用变量的地址作为实参。
18,什么时候需要使用“常引用”?
既要用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,应使用常引用。
19,引用作为函数返回值类型的格式、好处和需要遵守的规则?
好处:内存中不产生被返回值的副本。返回一个局部变量的引用是不可取的,因随着局部变量生存期的结束,相应的引用也会失效,产生runtime error。
1)不能返回局部变量的引用。局部变量在函数返回后被销毁,引用成为无所指的引用,程序进入未知状态。
2)不返回函数内部new分配的内存的引用。被函数返回的引用只是作为一个临时变量出现,没有被赋予一个实际的变量,这个引用指向的空间无法释放,造成memory leak。
3)可返回类成员的引用,最好是const。有必要将赋值操作封装在一个业务规则当中,如果其它对象可以获得该属性的非常量引用(或指针),对该属性的单纯赋值就会破坏业务规则的完整性。
4)刘操作符重载返回值申明为引用的作用
刘操作符<<和>>常希望连续使用,因此其返回值应该是一个仍然支持这2额操作符的流引用。返回一个刘对象,程序必须重新 拷贝构造一个新的流对象,即连续2个<<操作实际上是针对不同的对象,返回一个指针则不能连续使用<<操作符,因此返回一个流对 象引用是唯一选择。赋值操作符返回值必须是一个左值,以便可以被继续赋值。以上说明引用的重要性和无可替代性。
20,引用与多态的关系?
引用是除指针外另一个产生多态效果的手段。一个基类的引用可以指向它的派生类实例。
21,引用与指针的区别?
指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。
22,什么时候需要引用?
流操作符<<和>>、赋值操作符=的返回值;
拷贝构造函数的参数;
赋值操作符=的参数
23,结构和联合
同一时刻,联合中只存放一个被选中的成员,所有成员共用一块地址空间。而结构的所有成员都存在,不同成员的存放地址不同。
对联合的不同成员赋值,将会对其它成员重写,原来成员的值就不存在了,结构的不同成员赋值互不影响。
24,copy字符串
char * strcpy(char * strDst,const * strSrc){
if(strDst==NULL||strSrc==NULL)
return NULL;
if(strDst==strSrc)
return strDst;
char * tmpPtr=strDst;
while( (*strDst++=*strSrc++)!='\0'){;}
return tmpPtr;
}
25,new/delete与malloc/free的联系和区别?
都是在堆heap上进行动态内存操作。malloc需要指定内存分配的字节数并不能初始化对象,new会自动调用对象的constructor。delete会调用对象的destructor,而free不会调用对象的destructor。
What will be printed as the result of the operation below:
1)
void interviewTest1(){
char *p1="name";
char *p2;
p2=(char*)malloc(20);
memset (p2, 0, 20);
while(*p2++ = *p1++);
printf("%s\n",p2);
}
2)
main(){
int x=20,y=35;
x=y++ + x++;
y=++y + ++x;
printf("%d%dn",x,y);
}
3)
main(){
int x=5;
printf("%d,%d,%dn",x,x<<2,x>>2);
}
4)
#define swap(a,b) a=a+b;b=a-b;a=a-b;
int swap2(int a, int b)
{
int temp;
temp=a;
b=a;
a=temp;
return 0;
}
void main()
{
int x=5, y=10;
swap (x,y);
printf(“%d %dn”,x,y);
swap2(x,y);
printf(“%d %dn”,x,y);
}
5)
Answers:
1)empty string
2)5794
3)5,20,1
4)10,5 10,5
5)Cisco System isco System
6)
深入理解调试代码:
1)
void interviewTest1(){
char *p1="name";
char *p2;
p2=(char*)malloc(20);
memset (p2, 0, 20);
printf("p1=%s\n",p1);
int i=0;
while(*p2++ = *p1++){
printf("i=%d\n",++i);
printf("p1=%s\n",p1);
printf("p2=%s\n",--p2);
}
printf("p1=%s\n",p1);
printf("p2=%s\n",p2);
p1=p1-5;
p2=p2-5;
printf("p1=%s\n",p1);
printf("p2=%s\n",p2);
}
2)
void interviewTest2(){
int x=20,y=35;
x=y++ + x++;
printf("x=%d,y=%d\n",x,y);
y= ++y + ++x;
printf("x=%d,y=%d\n",x,y);
}
4)
void interviewTest3(){
int x=5, y=10;
//swap (x,y);
//printf("x=%d,y=%d\n",x,y);
swap2(x,y);
printf("x=%d,y=%d\n",x,y);
}
答案
试题一
3、
阅读(1050) | 评论(0) | 转发(0) |