一、华为面试题
1.写出判断ABCD四个表达式的是否正确, 若正确, 写出经过表达式中 a的值
int a = 4;
(A)a += (a++); (B) a += (++a) ;(C) (a++) += a;(D) (++a) += (a++);
a = ?
答:C错误,左侧不是一个有效变量,不能赋值,可改为(++a) += a;
改后答案依次为9,10,10,11
2.某32位系统下, C++程序,请计算sizeof 的值
char str[] = "HelloWorld";
char *p = str;
int n = 10;
请计算:
sizeof(str) = ? (1)
sizeof(p) = ? (2)
sizeof(n) = ? (3)
void Foo(char str[100])
{
请计算:
sizeof(str) = ? (4)
}
void *p = malloc(100);
请计算:
sizeof(p) = ? (5)
答:(1)11 (2)4 (3) 4 (4)4 (5)4
3.回答下面的问题
(1).#include<filename.h> 和 #include"filename.h" 有什么区别?
答:尖括号表示:先在系统目录查找所包含的文件,一般在要包含系统头文件时使用
双引号表示:先在当前程序所在的目录查找所包含的文件,一般在要包含自己写的文件时使用
再具体点就是:
<>搜索顺序为:系统目录 -->环境变量目录-->用户自定义目录
而"" 则是 用户自定义目录-->系统目录-->环境变量目录
(2).在C++ 程序中调用被 C 编译器编译后的函数,为什么要加 extern “C”声明?
答:函数和变量被C++编译后在符号库中的名字与C语言的不同,被extern "C"修饰的变量和函数是按照C语言方式编译和链接的。
由于编译后的名字不同,C++程序不能直接调用C函数。C++提供了一个C链接交换指定符号extern "C"来解决这个问题。
4.回答下面的问题
(1). void GetMemory(char **p,int num)
{
*p = (char*)malloc(num);
}
void Test()
{
char* str = NULL;
GetMemory(&str,100);
strcpy(str,"hello");
printf(str);
}
请问运行Test函数会有什么样的结果?
答:输出"hello"
(2). void Test()
{
char* str =(char*)malloc(100);
strcpy(str,"hello");
free(str);
if(str != NULL)
{
strcpy(str,"world");
printf(str);
}
}
请问运行Test函数会有什么样的结果?
答:输出"world"
(3). char* GetMemory()
{
char p[] = "hello world";
return p;
}
void Test()
{
char* str = NULL;
str = GetMemory();
printf(str);
}
请问运行Test函数会有什么样的结果?
答:无效的指针,输出不确定。
5.编写strcat函数
已知strcat函数的原型是char *strcat (char *strDest, const char *strSrc);
其中strDest 是目的字符串,strSrc 是源字符串。
(1)不调用C++/C 的字符串库函数,请编写函数 strcat
答:
VC源码:
char * __cdecl strcat (char * dst, const char * src)
{
char * cp = dst;
while( *cp )
cp++; /* find end of dst */
while( *cp++ = *src++ ) ; /* Copy src to end of dst */
return( dst ); /* return dst */
}
(2)strcat能把strSrc 的内容连接到strDest,为什么还要char * 类型的返回值?
答:方便赋值给其他变量。
6.C++中为什么用模板类?
解答:
(1)可用来创建动态增长和减小的数据结构
(2)它是类型无关的,因此具有很高的可复用性。
(3)它在编译时,而不是运行时检查数据类型,保证了类型安全
(4)它是平台无关的,可移植性
(5)可用于基本数据类型
7.程序什么时候应该使用线程,什么时候单线程效率高?
解答:
(1)耗时的操作使用线程,提高应用程序响应
(2)并行操作时使用线程,如C/S架构的服务器端并发线程响应用户的请求
(3)多CPU系统中,使用线程提高CPU利用率
8.C++中什么数据分配在栈或是堆中?
解答:
栈: 存放局部变量,函数调用参数,函数返回值,函数返回地址。由系统管理
堆:程序运行时动态申请,new 和malloc申请的内存就在堆上
9. TCP/IP建立连接的过程?(3-way shake)
解答:在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。
第一次握手:建立连接时,客户端发送syn包(syn = j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack = j +1),同时自己也发送一个SYN包(syn = k),
即SYN + ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN + ACK包,向服务器发送确认包ACK(ack = k + 1),此包发送完毕,
客户端和服务器进入ESTABLISHED状态,完成三次握手。
10. winsocket建立连接的主要实现步骤是什么?
解答:
服务器端:socker()建立套接字,绑定(bind)并监听(listen),用accept() 等待客户端连接
客户端:socker()建立套接字,连接(connect) 服务器,连接上后使用send() 和 recv(),在套接字上写读数据,
直至数据交换完毕,closesocket() 关闭套接字。
服务器端:accept() 发现有客户端连接,建立了一个新的套接字,自身重新开始等待连接。该新产生的套接字使用
send() 和 recv() 写读数据,直至数据交换完毕,closesocket() 关闭套接字。
11.动态链接库的两种方式?
解答:
调用一个DLL中的函数有两种方法:
(1)载入是动态链接(load-time dynamic linking),模块非常明确调用某个导出函数,使得他们就像本地函数一样。这需要
链接时链接那些函数所在DLL的导入库,导入库向系统提供了载入DLL时所需的信息及DLL函数定位。
(2)运行时动态链接(run-time dynamic linking),运行时可通过LoadLibrary 或 LoadLibraryEx函数载入DLL。DLL载入后,模块
可以通过调用GetProcAddress获取DLL函数的出口地址,然后就可以通过返回的函数指针调用DLL函数了。如此即可避免
导入库文件了。