面试经典试题

C++经典面试题(最全,面中率最高) 答:引用就是某个目标变量的“别名”(alias),对应用的操作与对变量直接操作效果完全相同。申明一个引用的时候,切记要对其进行初始化。引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,不能再把该引用名作为其他变量名的别名。声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。不能建立数组的引用。 阅读详情
面试经典试题

Author: Vince      来源:http://blog.youkuaiyun.com/vincetest

————即使你是个编程高手,你在面试前也应该要看看这套题,她也许会给你带来好运,否则你有可能后悔当初为什么没有看而跳楼自杀,这样我会很内疚的。这套题看似简单,但你未必能得高分,即使你看不懂也要把她背下来!  

1       编程基础

1.1    基本概念

1.         const的理解:const char*, char const*, char*const的区别问题几乎是C++面试中每次    都会有的题目。 事实上这个概念谁都有只是三种声明方式非常相似很容易记混。 Bjarne在他的The C++ Programming Language里面给出过一个助记的方法: 把一个声明从右向左读。

char  * const cp; ( * 读成 pointer to )

cp is a const pointer to char

const char * p;

p is a pointer to const char;

char const * p;

同上因为C++里面没有const*的运算符,所以const只能属于前面的类型。

2.         c指针

int *p[n];-----指针数组,每个元素均为指向整型数据的指针。

int (*)p[n];------p为指向一维数组的指针,这个一维数组有n个整型数据。

int *p();----------函数带回指针,指针指向返回的值。

int (*)p();------p为指向函数的指针。

3.         数组越界问题

下面这个程序执行后会有什么错误或者效果:

 #define MAX 255

int main()

{

    unsigned char A[MAX],i;

    for (i=0;i<=MAX;i++)

        A[i]=i;

}

解答:MAX=255,数组A的下标范围为:0..MAX-1,这是其一,其二 当i循环到255时,循环内执行: A[255]=255;这句本身没有问题,但是返回for (i=0;i<=MAX;i++)语句时,由于unsigned char的取值范围在(0..255),i++以后i又为0了..无限循环下去.

注:char类型为一个字节,取值范围是[-128,127],unsigned char [0 ,255]

4.         C++:memset ,memcpy 和strcpy 的根本区别?  

#include "memory.h"

memset用来对一段内存空间全部设置为某个字符,一般用在对定义的字符串进行初始化为‘ '或‘/0';例:char a[100];memset(a, '/0', sizeof(a));

memcpy用来做内存拷贝,你可以拿它拷贝任何数据类型的对象,可以指定拷贝的数据长度;例:char a[100],b[50]; memcpy(b, a, sizeof(b));注意如用sizeof(a),会造成b的内存地址溢出。

strcpy就只能拷贝字符串了,它遇到'/0'就结束拷贝;例:char a[100],b[50];strcpy(a,b);如用strcpy(b,a),要注意a中的字符串长度(第一个‘/0'之前)是否超过50位,如超过,则会造成b的内存地址溢出。

strcpy

原型:extern char *strcpy(char *dest,char *src);

用法:#include

功能:把src所指由NULL结束的字符串复制到dest所指的数组中。

说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。

返回指向dest的指针。

memcpy

原型:extern void *memcpy(void *dest, void *src, unsigned int count);

用法:#include

功能:由src所指内存区域复制count个字节到dest所指内存区域。

说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针。

Memset

原型:extern void *memset(void *buffer, char c, int count);

用法:#include

功能:把buffer所指内存区域的前count个字节设置成字符c。

说明:返回指向buffer的指针。

5.         ASSERT()是干什么用的

ASSERT()是一个调试程序时经常使用的宏,在程序运行时它计算括号内的表达式,如果表达式为FALSE (0), 程序将报告错误,并终止执行。如果表达式不为0,则继续执行后面的语句。这个宏通常原来判断程序中是否出现了明显非法的数据,如果出现了终止程序以免导致严重后果,同时也便于查找错误。例如,变量n在程序中不应该为0,如果为0可能导致错误,你可以这样写程序:

......

ASSERT( n != 0);

k = 10/ n;

......

ASSERT只有在Debug版本中才有效,如果编译为Release版本则被忽略。

assert()的功能类似,它是ANSI C标准中规定的函数,它与ASSERT的一个重要区别是可以用在Release版本中。

6.         system("pause");系统的暂停程序,按任意键继续,屏幕会打印,"按任意键继续。。。。。" 省去了使用getchar();

7.         请问C++的类和C里面的struct有什么区别?

c++中的类具有成员保护功能,并且具有继承,多态这类oo特点,而c里的struct没有

8.         请讲一讲析构函数和虚函数的用法和作用?

析 构函数也是特殊的类成员函数,它没有返回类型,没有参数,不能随意调用,也没有重载。知识在类对象生命期结束的时候,由系统自动调用释放在构造函数中分配 的资源。这种在运行时,能依据其类型确认调用那个函数的能力称为多态性,或称迟后联编。另:析构函数一般在对象撤消前做收尾工作,比如回收内存等工作,虚 拟函数的功能是使子类可以用同名的函数对父类函数进行重载,并且在调用时自动调用子类重载函数,如果是纯虚函数,则纯粹是为了在子类重载时有个统一的命名 而已。

9.         全局变量和局部变量有什么区别?实怎么实现的?操作系统和编译器是怎么知道的?

全局变量的生命周期是整个程序运行的时间,而局部变量的生命周期则是局部函数或过程调用的时间段。其实现是由编译器在编译时采用不同内存分配方法。全局变量在main函数调用后,就开始分配,如果是静态变量则是在main函数前就已经初始化了。而局部变量则是在用户栈中动态分配的(还是建议看编译原理中的活动记录这一块)

10.     8086是多少尉的系统?在数据总线上是怎么实现的?

8086系统是16位系统,其数据总线是20位。

1.2    程序设计

1.         编写用C语言实现的求n阶阶乘问题的递归算法:

long int fact(int n)
{

    int x;

    long int y;

    if(n<0)  

    {

       printf("error!");

    }

    if(n==0)

       return 1;

    x=n-1;

    y=fact(x);

    return (n*y);

}

2.         二分查找算法:

1)        递归方法实现:

int BSearch(elemtype a[],elemtype x,int low,int high)

/*在下届为low,上界为high的数组a中折半查找数据元素x*/

{

  int mid;

  if(low>high) return -1;

  mid=(low+high)/2;

  if(x==a[mid]) return mid;

  if(x<a[mid]) return(BSearch(a,x,low,mid-1));

  else return(BSearch(a,x,mid+1,high));

}

2)        非递归方法实现:

int BSearch(elemtype a[],keytype key,int n)

{

  int low,high,mid;

  low=0;high=n-1;

  while(low<=high) 

   {

      mid=(low+high)/2;

      if(a[mid].key==key) return mid;

      else if(a[mid].key<key) low=mid+1;

      else high=mid-1;

   }

  return -1;

}

3.         递归计算如下递归函数的值(斐波拉契):

f(1)=1

f(2)=1

f(n)=f(n-1)+f(n-2) n>2

解:

int f(int n)

{

        int i,s,s1,s2;

        s1=1;/*s1用于保存f(n-1)的值*/

        s2=1;/*s2用于保存f(n-2)的值*/

        s=1;

        for(i=3;i<=n;i++)

{

       s=s1+s2;

       s2=s1;

       s1=s;

    }

return(s);

}

4.         交换两个数,不用第三块儿内存:

int a = ……;

int b = ……;

a = a + b;

b = a - b;

a = a - b;

5.         冒泡排序:

void BubbleSort(elemtype x[],int n)

{

        int i,j;

        elemtype temp;

        for(i=1;i<n;i++) 

        for(j=0;j<n-i;j++)

{

                if(x[j].key>x[j+1].key) 

                {

                    temp=x[j];

                    x[j]=x[j+1];

                    x[j+1]=temp;

                }

}

}

6.         c语言 文件读写

#include "stdio.h"

main()

{

        FILE *fp;

        char ch,filename[10];

        scanf("%s",filename);

        if((fp=fopen(filename,"w")==NULL)

        {

printf("cann't open file/n");

exit(0);

  }

  ch=getchar();

  while(ch!='#')

  {

       fputc(ch,fp);

       putchar(ch);

       ch=getchar();

  }

  fclose(fp);

}

7.         winsocket编程

#include <Winsock2.h>

#include <stdio.h>

void main()

{

       WORDwVersionRequested;

        WSADATA wsaData;

        int err;

        wVersionRequested = MAKEWORD(1,1);

        err = WSAStartup(wVersionRequested,&wsaData);

        if( err != 0)

{

            return; 

        }

        if(LOBYTE( wsaData.wVersion ) != 1||

           HIBYTE( wsaData.wVersion) != 1)

{

            WSACleanup();

            return;

        }

        SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0);

        SOCKADDR_IN addrSrv;

       addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);

        addrSrv.sin_family=AF_INET;

        addrSrv.sin_port=htons(6000);

       bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

       listen(sockSrv,5);

        SOCKADDR_IN addrClient;

        int len=sizeof(SOCKADDR);

        while(1)

        {

            SOCKET sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len);

            char sendBuf[100];

            sprint(sendBuf,"Welcome %s to http://www.sunxin.org",

           inet_ntoa(addrClient.sin_addr));

            send(sockConn,sendBuf,strlen(sendBuf)+1,0);

            char recvBuf[100];

           recv(sockConn,recvBuf);

            printf("%s/n",recvBuf);

            closesocket(sockConn);

            WSACleanup();

        } 

}

注:这是Server端;File->New->Win32 Console Application,工程名:TcpSrv;然后,File->New->C++ Source File,文件名:TcpSrv;在该工程的Setting的Link的Object/library modules项要加入ws2_32.lib

#include <Winsock2.h>

#include <stdio.h>

void main()

{

        WORDwVersionRequested;

        WSADATA wsaData;

        int err;

        wVersionRequested = MAKEWORD(1,1);

        err = WSAStartup(wVersionRequested,&wsaData);

        if( err != 0)

{

            return; 

        }

        if(LOBYTE( wsaData.wVersion ) != 1||

            HIBYTE( wsaData.wVersion) != 1)

{

            WSACleanup();

            return;

        }

        SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);

        SOCKADDR_IN addrSrv;
        addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");

        addrSrv.sin_family=AF_INET;

        addrSrv.sin_porthtons(6000);

        connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

char recvBuf[100];

recv(sockClient,recvBuf,100,0);

printf("%s/n",recvBuf);

send(sockClient,"This is zhangsan",strlen("This is zhangsan")+1,0); 

        closesocket(sockClient);

        WSACleanup();

}

注:这是Client端;File->New->Win32 Console Application,工程名:TcpClient;然后,File->New->C++ Source File,文件名:TcpClient;同理,在该工程的Setting的Link的Object/library modules项要加入ws2_32.lib

8.         类的知识

C++

#include <iostream.h>

class human

{

public:

human(){ human_num++;};

static int human_num;

~human()

{

human_num--;

print();

}

void print()

{

cout<<"human num is: "<<human_num<<endl;

}

protected:

private:

};

int human::human_num = 0;

human f1(human x)

{

x.print();

return x;

}

int main(int argc, char* argv[])

{

human h1;

h1.print();

human h2  = f1(h1);

h2.print();

return 0;

}

输出:

1

1

0

0

-1

-2

----------------------------

分析:

human h1;       //调用构造函数,---hum_num = 1;

h1.print();     //输出:"human is 1"

human h2  = f1(h1); //再调用f1(h1)的过程中,由于函数参数是按值传递对象,调用默认的复制构造函数,它并没有对hum_num++,所以hum_num 仍= 1,所以x.print()输出:"human is 1";   在推出f1函数时,要销毁X,调用析构函数(human_num--),输出:"human is 0"(,由于该函数返回一个human 对象,所以又调用默认构造函数,创建一个临时对象(human_num = 0;),把临时对象赋给h2,又调用默认构造函数(  human_num = 0);   h2.print();   //输出: human is 0;

//在退出main()函数是,先销毁h2,调用析构函数(human_num--),输出"human_num is -1" 然后销毁h1,调用析构函数(--),输出"human_num is -2"

1.3    Windows的消息机制

1.         Windows的消息机制1

       Windows是一个消息(Message)驱动系统。Windows的消息提供了应用程序之间、应用程序与Windows系统之间进行通信的手段。应用程序想要实现的功能由消息来触发,并且靠对消息的响应和处理来完成。

       Windows系统中有两种消息队列:系统消息队列和应用程序消息队列。计算机的所有输入设备由Windows监控。当一个事件发生时,Windows先将输入的消息放入系统消息队列中,再将消息拷贝到相应的应用程序消息队列中。应用程序的消息处理程序将反复检测消息队列,并把检测到的每个消息发送到相应的窗口函数中。这便是一个事件从发生至到达窗口函数必须经历的过程。

       必须注意的是,消息并非是抢占性的,无论事件的缓急,总是按照到达的先后派对,依次处理(一些系统消息除外),这样可能使一些实时外部事件得不到及时处理。

2.         Windows的消息机制2

       Windows中的消息是放在对应的进程的消息队列里的。可以通过GetMessage取得,并且对于一般的消息,此函数返回非零值,但是对于WM_QUIT消息,返回零。可以通过这个特征,结束程序。当取得消息之后,应该先转换消息,再分发消息。所谓转换,就是把键盘码的转换,所谓分发,就是把消息分发给对应的窗口,由对应的窗口处理消息,这样对应窗体的消息处理函数就会被调用。两个函数可以实现这两个功能:TranslateMessage和DispatchMessage。

       另外,需要注意,当我们点击窗口的关闭按钮关闭窗口时,程序并没有自动退出,而是向程序发送了一个WM_DESTROY消息(其实过程是这样的,首先向程序发送WM_CLOSE消息,默认的处理程序是调用DestroyWindow销毁窗体,从而引发WM_DESTROY消息),此时在窗体中我们要响应这个消息,如果需要退出程序,那么就要向程序发送WM_QUIT消息(通过PostQuitMessage实现)。一个窗体如果想要调用自己的消息处理函数,可以使用SendMessage向自己发消息。

       如上所述,大部分(注意是大部分)的消息是这样传递的:首先放到进程的消息队列中,之后由GetMessage取出,转换后,分发给对应的窗口。这种消息成为存储式消息。存储式消息基本上是使用者输入的结果,以击键(如WM_KEYDOWN和WM_KEYUP讯息)、击键产生的字符(WM_CHAR)、鼠标移动(WM_MOUSEMOVE)和鼠标按钮(WM_LBUTTONDOWN)的形式给出。存储式消息还包含时钟消息(WM_TIMER)、更新消息(WM_PAINT)和退出消息(WM_QUIT)。但是也有的消息是直接发送给窗口的,它们被称为非存储式消息。例如,当WinMain调用CreateWindow时,Windows将建立窗口并在处理中给窗口消息处理函数发送一个WM_CREATE消息。当WinMain调用ShowWindow时,Windows将给窗口消息处理函数发送WM_SIZE和WM_SHOWWINDOW消息。当WinMain调用UpdateWindow时,Windows将给窗口消息处理函数发送WM_PAINT消息。


 

2       网络知识

2.1    OSI和TCP/IP

1.         OSI的七层网络结构图(功能及特点)

1)   物理层:为数据链路层提供物理连接,在其上串行传送比特流,即所传送数据的单位是比特。此外,该层中还具有确定连接设备的电气特性和物理特性等功能。

2)   数据链路层:负责在网络节点间的线路上通过检测、流量控制和重发等手段,无差错地传送以帧为单位的数据。为做到这一点,在每一帧中必须同时带有同步、地址、差错控制及流量控制等控制信息。

3)   网络层:为了将数据分组从源(源端系统)送到目的地(目标端系统),网络层的任务就是选择合适的路由和交换节点,使源的传输层传下来的分组信息能够正确无误地按照地址找到目的地,并交付给相应的传输层,即完成网络的寻址功能。

4)   传输层:传输层是高低层之间衔接的接口层。数据传输的单位是报文,当报文较长时将它分割成若干分组,然后交给网络层进行传输。传输层是计算机网络协议分层中的最关键一层,该层以上各层将不再管理信息传输问题。

5)   会话层:该层对传输的报文提供同步管理服务。在两个不同系统的互相通信的应用进程之间建立、组织和协调交互。例如,确定是双工还是半双工工作。

6)   表示层:该层的主要任务是把所传送的数据的抽象语法变换为传送语法,即把不同计算机内部的不同表示形式转换成网络通信中的标准表示形式。此外,对传送的数据加密(或解密)、正文压缩(或还原)也是表示层的任务。

7)   应用层:该层直接面向用户,是OSI中的最高层。它的主要任务是为用户提供应用的接口,即提供不同计算机间的文件传送、访问与管理,电子邮件的内容处理,不同计算机通过网络交互访问的虚拟终端功能等。

2.         TCP/IP(功能及特点)

1)   网络接口层:这是TCP/IP协议的最低一层,包括有多种逻辑链路控制和媒体访问协议。网络接口层的功能是接收IP数据报并通过特定的网络进行传输,或从网络上接收物理帧,抽取出IP数据报并转交给网际层。

2)   网际网层(IP层):该层包括以下协议:IP(网际协议)、ICMP(Internet Control Message Protocol,因特网控制报文协议)、ARP(Address Resolution Protocol,地址解析协议)、RARP(Reverse Address Resolution Protocol,反向地址解析协议)。该层负责相同或不同网络中计算机之间的通信,主要处理数据报和路由。在IP层中,ARP协议用于将IP地址转换成物理地址,RARP协议用于将物理地址转换成IP地址,ICMP协议用于报告差错和传送控制信息。IP协议在TCP/IP协议组中处于核心地位。

3)   传输层:该层提供TCP(传输控制协议)和UDP(User Datagram Protocol,用户数据报协议)两个协议,它们都建立在IP协议的基础上,其中TCP提供可靠的面向连接服务,UDP提供简单的无连接服务。传输层提供端到端,即应用程序之间的通信,主要功能是数据格式化、数据确认和丢失重传等。

4)   应用层:TCP/IP协议的应用层相当于OSI模型的会话层、表示层和应用层,它向用户提供一组常用的应用层协议,其中包括:Telnet、SMTP、DNS等。此外,在应用层中还包含有用户应用程序,它们均是建立在TCP/IP协议组之上的专用程序。

3.         OSI参考模型和TCP/IP参考模型的区别:

1)   OSI模型有7层,TCP/IP只有4层;

2)   OSI先于协议出现,因此不会偏向于任何一组特定的协议,通用性更强,但有些功能不知该放哪一层上,因此不得不加入一些子层;TCP/IP后于协议出现,仅是将已有协议的一个描述,因此两者配合的非常好;但他不适合其他的协议栈,不容易描述其他非TCP/IP的网络;

3)   OSI中网络层同时支持无连接和面向连接的通信,但在传输层上只支持面向连接的通信;TCP/IP中网络层只支持无连接通信,传输层同时支持两种通信;

4)   在技术发生变化时,OSI模型比TCP/IP模型中的协议更容易被替换。

4.         请你详细的解释一下IP协议的定义,在哪个层上面,主要有什么作用? TCP与UDP呢? 

解:与IP协议配套使用的还有三个协议:

ARP-地址解析协议

RARP-逆地址解析协议

ICMP-因特网控制报文协议ICMP

IP协议-网际协议

IP地址、IP包头

2.2    交换机和路由器

1.         请问交换机和路由器分别的实现原理是什么?分别在哪个层次上面实现的?

将网络互相连接起来要使用一些中间设备(或中间系统),ISO的术语称之为中继(relay)系统。根据中继系统所在的层次,可以有以下五种中继系统:

1)       物理层(即常说的第一层、层L1)中继系统,即转发器(repeater)。

2)       数据链路层(即第二层,层L2),即网桥或桥接器(bridge)。

3)       网络层(第三层,层L3)中继系统,即路由器(router)。

4)       网桥和路由器的混合物桥路器(brouter)兼有网桥和路由器的功能。

5)       在网络层以上的中继系统,即网关(gateway).

当中继系统是转发器时,一般不称之为网络互联,因为这仅仅是把一个网络扩大了,而这仍然是一个网络。高层网关由于比较复杂,目前使用得较少。因此一般讨论网络互连时都是指用交换机和路由器进行互联的网络。本文主要阐述交换机和路由器及其区别。  

2.         第二层交换机和路由器的区别:

传统交换机从网桥发展而来,属于OSI第二层即数据链路层设备。它根据MAC地址寻址,通过站表选择路由,站表的建立和维护由交换机自动进行。路由器属于OSI第三层即网络层设备,它根据IP地址进行寻址,通过路由表路由协议产生。因特网的路由选择协议:内部网关协议IGP和外部网关协议EGP

3.         第三层交换机和路由器的区别:

在第三层交换技术出现之前,几乎没有必要将路由功能器件和路由器区别开来,他们完全是相同的:提供路由功能正在路由器的工作,然而,现在第三层交换机完全能够执行传统路由器的大多数功能。

综 上所述,交换机一般用于LAN-WAN的连接,交换机归于网桥,是数据链路层的设备,有些交换机也可实现第三层的交换。路由器用于WAN-WAN之间的连 接,可以解决异性网络之间转发分组,作用于网络层。他们只是从一条线路上接受输入分组,然后向另一条线路转发。这两条线路可能分属于不同的网络,并采用不 同协议。相比较而言,路由器的功能较交换机要强大,但速度相对也慢,价格昂贵,第三层交换机既有交换机线速转发报文能力,又有路由器良好的控制功能,因此 得以广播应用。


 

3       高质量编程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 分)
void Func ( char str[100])
{
   
请计算
    sizeof( str ) = 4
(2 分)
}
char str[] = “Hello” ;
char *p = str ;
int n = 10;
请计算
sizeof (str ) = 6
(2 分)
sizeof ( p ) = 4
(2 分)
sizeof ( n ) = 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";
    return p;
}
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");
    printf(str);
}
请问运行Test 函数会有什么样的结果?
答:(1)能够输出hello;(2)内存泄漏


void Test(void)
{
    char *str = (char *) malloc(100);
    strcpy(str, “hello”);
    free(str);
    if(str != NULL)
    {
        strcpy(str, “world”);
        printf(str);
    }
}
请问运行Test 函数会有什么样的结果?
答:篡改动态内存区的内容,后果难以预
料,非常危险。
因为free(str);之后,str 成为野指针,
if(str != NULL)
语句不起作用。

五、编写strcpy 函数(10 分)
已知strcpy 函数的原型是
char *strcpy(char *strDest, const char *strSrc);
其中strDest 是目的字符串,strSrc 是源字符串。
(1)不调用C++/C 的字符串库函数,请编写函数 strcpy
char *strcpy(char *strDest, const char *strSrc);
{
    assert((strDest!=NULL) && (strSrc !=NULL)); // 2
分

    char *address = strDest; // 2
分
    while( (*strDest++ = * strSrc++) != ‘/0’ ) // 2
分
    NULL ;
    return address ; // 2
分
}

(2)strcpy 能把strSrc 的内容复制到strDest,为什么还要char * 类型的返回值?
答:为了实现链式表达式。 // 2 分
例如 int length = strlen( strcpy( strDest, “hello world”) );

六、编写类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_data; //
用于保存字符串
};
请编写String 的上述4 个函数。
标准答案:
// String
的析构函数
String::~String(void) // 3
分
{
    delete [] m_data;
    //
由于m_data 是内部数据类型,也可以写成 delete m_data;
}


// String
的普通构造函数
String::String(const char *str) // 6
分
{
    if(str==NULL)
    {
        m_data = new char[1]; //
若能加 NULL 判断则更好
        *m_data = ‘/ 0’ ;
    }
    else
    {
        int length = strlen(str);
        m_data = new char[length+1]; //
若能加 NULL 判断则更好
        strcpy(m_data, str);
     }
}


//
拷贝构造函数
String::String(const String &other) // 3
分
{
    int length = strlen(other.m_data);
    m_data = new char[length+1]; //
若能加 NULL 判断则更好
    strcpy(m_data, other.m_data);
}


//
赋值函数
String & String::operate =(const String &other) // 13
分
{
    // (1)
检查自赋值 // 4 分
    if(this == &other)
    return *this;
    // (2)
释放原有的内存资源 // 3 分
    delete [] m_data;
    //
(3)分配新的内存资源,并复制内容 // 3 分
    int length = strlen(other.m_data);
    m_data = new char[length+1]; //
若能加 NULL 判断则更好
    strcpy(m_data, other.m_data);
    //
(4)返回本对象的引用 // 3 分
    return *this;
}
80道经典常见测试面试题 这不止是一份面试清单,更是一种“被期望的责任”,因为有无数个待面试着,希望从这篇文章中,找出通往期望公司的“钥匙”,所以上面的每道选题都是结合我自身的经验,于千万个面试题中经过艰辛的两周,一个题一个题筛选出来再校对好答案和格式做出来的,面试的答案也是再三斟酌,生怕误人子弟是小,影响他人的“仕途”才是大过,所以如有纰漏,还请读者朋友们在评论区不吝指出。35、基于目前中国的国情,大多数公司的项目进度紧张、人员较少、需求文梢根本没有或者很不规范,你认为在这种情况下怎样保证软件的质量?测试脚本两者的关系是什么? 阅读详情

相关推荐

经典Hive SQL面试题

第一题 需求 我们有如下的用户访问数据 userId visitDate visitCount u01 2017/1/21 5 u02 2017/1/23 6 u03 2017/1/22 8 u04 2017/1/20 3 u01 2017/1/23 6 u01 2017/2/21 8 U02 2017/1/23 6 U01 2017/2/22 ...

jmx_bigdata的博客 3803

【附答案】C/C++ 最常见50道面试题

在编程中,变量的声明指的是告知编译器变量的名称和类型,但不分配内存空间。声明可以多次,常见于头文件中,用于模块间的接口声明。使用extern关键字声明的变量,意味着其定义在别处,通常在另一个文件中。相对地,定义则是创建一个具有存储空间的变量实例。定义只能有一次,通常在源文件中,确保为变量分配内存空间。例如,全局变量和局部变量的定义就是分配内存并初始化的过程。

叫好与叫座虽然不是对立面,但想在同一个作品中达到双重效果很难。 1万+

20道经典Redis面试题

整理了20道经典Redis面试题,希望对大家有帮助。Redis,英文全称是(远程字典服务),是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。与MySQL数据库不同的是,Redis的数据是存在内存中的。它的读写速度非常快,每秒可以处理超过10万次读写操作。因此redis被广泛应用于缓存,另外,Redis也经常用来做分布式锁。除此之外,Redis支持事务、持久化、LUA 脚本、LRU 驱动事件、多种集群方案。

小赵的博客 3348

50个C/C++面试题

面试题1:变量的声明和定义有什么区别  为变量分配地址和存储空间的称为定义,不分配地址的称为声明。一个变量可以在多个地方声明,但是只在一个地方定义。加入extern修饰的是变量的声明,说明此变量将在文件以外或在文件后面部分定义。  说明:很多时候一个变量,只是声明不分配内存空间,直到具体使用时才初始化,分配内存空间,如外部变量。  面试题2:写出bool 、int、 float、

沙漠中的一粒沙 1万+

MyBatis最经典的20道面试题,你都会了吗?

MyBatis是一款优秀的持久层框架,在Java开发中广受欢迎。下面是一些常见的MyBatis面试题,以及相应的案例分析,希望对你的学习和面试有所帮助。MyBatis是一款基于Java的持久层框架,它通过XML描述符或注解将对象与存储过程或SQL语句进行映射,实现了面向对象编程与关系数据库的映射。动态SQL是MyBatis中的一项强大功能,它可以根据条件判断动态拼接SQL语句,避免硬编码。例如,动态SQL可以在条件成立时插入WHERE子句:

私聊前往站内信:https://i.youkuaiyun.com/#/msg/chat/weixin_44976692 3万+

经典c/c++笔试面试题汇总

多年收集的c、c++经典书籍汇总 华为笔试面试题面试宝典 嵌入式 深入理解指针

第一章:10道C/C++经典面试题

http://blog.youkuaiyun.com/rl529014/article/details/52029524 版权声明:本文为博主原创文章,未经博主允许不得转载。 目录(?)[+] 面试题 1:变量的声明和定义有什么区别 为变量分配地址和存储空间的称为定义,不分配地址的称为声明。 一个变量可以在多个地方声明,但是只在一个地方定义。 加

ymxwz的专栏 667

50个常见的c与c++面试题

很好的c与c++面试的试题汇总。里面包括很多常用的但容易忽略的问题,欢迎大家踊跃下载。

C/C++经典面试题全集

最后一个意味着a 是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS 下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。栈:在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C 编译器中,参数是由右往左入栈的,然后是函数中的局部变量。

2301_76630307的博客 239

c/c++面试人员必看,经典面试题目,常见面试官会出的考题

分高,但质量也高,内函几乎各大公司的面试题以及面试技巧,和容易被面试官为难的问题、陷阱。当初我同学们各个公司去面试,最后统计了一下,不能说全部,但70%不离其中,如果把这些看完,技术面试通过没有问题!绝不会后悔的面试资源,给大家的面试c/c++面试铺平一条宽敞之路!

GMSL Strapping Pins CFG0/CFG1 应用

如果 0x13.bit3 = 0, 则是链路没有 Locked,需要去排查下具体问题(通常是工作模式配置问题)如果遇到 Link 无法建立(Locked),电源没有问题的情况下,多半是加串器和解串器的工作模式不匹配。芯片在上电时,会检测这两个管脚的电压,根据不同的电压值,芯片进入到不同的工作模式。一对加串器和解串器,只要工作模式匹配得当,Link Locked,便能够正常工作。ADI 已经充分考虑了用户的需求,尽可能的降低的芯片的使用和配置复杂度。GMSL 的解串器也是类似的配置,具体请参考对应的规格书。

iStoneWalker的博客 1271

IT行业经典面试题,121套面试题

 IT行业经典面试题,121套面试题资源大小: 580.80KB资源类型:发布人: eyelife        发布日期: 2天前Tag: 名企,计算机 资源分: 10下载人数: 857 4.33/347人评分 12 3 4 5 <!--评论收藏 举报共享-->评论 分享 收藏 举报 上传

首席技术执行官CTO(Chief Technology Officer)|技术总监--邓斌博客 5242

别再手动填数据了!Vivado里用.coe文件给ROM IP核预装数据的保姆级教程

本文详细介绍了在Vivado中使用.coe文件为ROM IP核预装数据的全流程教程,包括文件格式规范、数据转换技巧和Vivado配置指南。通过自动化数据加载,开发者可以显著提升FPGA开发效率,避免手动输入错误,适用于查找表、波形存储等多种应用场景。

weixin_33377602的博客 337

经典面试题

经典面试题

YEYUANGEN的专栏 1076

代码实现ROS2bag录制数据和回放数据(C++)

ROS2的ROS2bag功能可以将指定Topic中的数据以.db3的格式(不同于ROS)保存到本地文件中。读取文件数据可以实现数据回放。

m0_57124501的博客 3256

SAP CKMLCP 月结7大常见报错:从“未找到成本核算运行”到“物料占用”的完整解决方案

本文深入解析SAP CKMLCP月结过程中的7大常见报错,从权限问题到数据一致性错误,提供系统化的解决方案。重点解决'未找到成本核算运行'和'物料占用'等典型问题,帮助财务人员高效完成成本核算月结,确保数据准确性。

weixin_30299709的博客 415

十道经典的逻辑面试题

3、公司办公室有五位职员。元旦快到了,元旦谁来值班?大家商定的意见,可以概括为以下四条:) P" w3 H% W, v/ ~- e/ }   A、如果E来值班,那么A、C中来一人。B、只有E来,D才来。, V6 i6 |' ?# c& K9 Q( L: s

sjxbf的专栏 2374

从0到1做AI漫剧:即梦+豆包+剪映+红果全流程实战

AI视频生成正在重塑内容创作的生产方式,它让原本高门槛的影视制作,变成了一条由文本、画面、剪辑与分发环节协同的流水线。理解其底层原理,在于将大模型的语义理解、图像生成与视频合成能力,与工程化的流程管理相结合,从而实现从创意到成片的自动化输出。这种技术的价值,不仅体现在降低制作成本,更在于让个人创作者能够独立完成高质量短剧,并快速迭代内容。在短剧、短视频、广告营销等场景中,利用即梦生成画面、豆包编写剧本、剪映完成剪辑、红果进行分发的组合,已成为一种被广泛验证的实践路径。本文聚焦AI漫剧制作,从环境准备、分镜设

weixin_34072637的博客 382

经典面试题100道

经典面试题100道 ,很不错哦附件: 面试题.doc  更多精彩内容请访问  www.17testing.com

1120

VScode利用EIDE和cortex-debug进行stm32开发(也适用51)

你是否因为keil页面太丑而烦恼,你是否因为keil编译太慢而恼怒,ok阿,今天也是给大家带来怎么在vscode上进行stm32的编程(我不会告诉你,我搞了好几天才搞好的💔💔💔)为什么是简单介绍?因为太啰嗦了,我嫌麻烦😋,大家可以去EIDE的官方文档去看。

weixin_73952614的博客 9389

5种隐藏代码到图片的实用技巧:从Notepad++到Linux命令全解析

本文详细解析了5种将代码或文本隐藏到图片中的实用数据隐写技巧。从Notepad++尾部追加、Windows命令行合并,到编辑图像元数据、使用十六进制编辑器,再到Linux的cat/dd命令,全面覆盖了从图形界面到命令行的工程化实践方法,帮助开发者和安全研究人员掌握隐蔽信息传输与存储的核心技术。

hh234的博客 353

29个运维经典面试题

前言 这篇博文参考阿铭linux-28个运维经典面试题,并对其中的一些题目进行扩展和解析。如有侵权,请联系我删除~再次感谢阿铭老师的分享。 大家有空可以看看阿铭老师的教程~ 第一题:Linux如何挂载windows下的共享目录? mount.cifs //IP地址/server /mnt/server -o user=administrator,password=123456 linux 下的se...

weixin_34413357的博客 4万+

基于FPGA的万兆以太网学习(1)

万兆(10G) 以太网测速视频:SFP+屏蔽笼可以插入千兆或万兆光模块。SFP+信号定义与 SFP 一致。

baidu_34971492的博客 2250

一些经典的谷歌面试题

(一些经典的谷歌面试题)

cmdssd1的专栏 897

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

WPF经典面试题全集

以上这些问题涵盖了WPF的核心概念和高级功能,包括数据绑定、依赖属性、MVVM 模式、资源管理、动画、主题切换以及拖放操作等。这些知识点对于理解和深入掌握WPF开发至关重要,同时也是面试中常见的考察点。

m0_58717895的博客 7917

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

上一篇: 软件公司是如何倒闭的
下一篇: 华为公司 java 面试题
kevin_long
博客等级 码龄20年 30粉丝 45原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值