资源描述
C/C++面试题大汇总收藏
最近因为找工作,搜集了诸多C语言方面方面的面试题以及答案。目前新工作搞定了,决定把这些资料发出来, 送给有需要的朋友,省得再象我同样到处搜寻,实在辛苦。
公布之前先申明两点:
1 所有资料来自网络(重要是CSDN),本人只是搜集和转发。
2所有问题解答(尤其是代码)只是参考,不确保正确。
先发基本问题,再发编程问题..........
想成为嵌入式程序员应懂得的0x10个基本问题:
预处理器(Preprocessor)
1 . 用预处理指令#define 申明一个常数,用以表白1年中有多少秒(忽视闰年问题)
#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
我在这想看到几件事情:
1) #define语法的基本知识(例如:不能以分号结束,括号的使用,等等)
2)懂得预处理器将为你计算常数体现式的值,因此,直接写出你是怎样计算一年中有多少 秒而不是计算出实际的值,是更清楚而没有代价的。
3)意识到这个体现式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。
4)假如你在你的体现式中用到UL(表示无符号长整型),那么你有了一个好的起点。记住,第一印象很重要。
2 . 写一个"标准"宏MIN ,这个宏输入两个参数并返回较小的一个。
#define MIN(A,B) ((A)< = (B) ? (A) : (B))
这个测试是为下面的目标而设的:
1)标识#define在宏中应用的基本知识。这是很重要的。因为在 嵌入(inline)操作符 变为标准C的一部分之前,宏是以便产生嵌入代码的唯一措施,对于嵌入式系统来说,为了能达成要求的性能,嵌入代码常常是必须的措施。
2)三重条件 操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生比if-then-else更优化的代码,了解这个使用方法是很重要的。
3)懂得在宏中小心地把参数用括号括起来
4) 我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什么事?
least = MIN(*p++, b);
3. 预处理器标识#error的目标是什么?
假如你不懂得答案,请看参考文献1。这问题对辨别一个正常的伙计和一个书呆子是很有用的。只 有书呆子才会读C语言课本的附录去找出象这种问题的答案。当然假如你不是在找一个书呆子,那么应试者最佳希望自己不要懂得答案。
死循环(Infinite loops)
4. 嵌入式系统中常常要用到无限循环,你怎么样用C编写死循环呢?
这个问题用几个处理方案。我首选的方案是:
while(1)
{
}
某些程序员更喜欢如下方案:
for(;;)
{
}
这个实现方式让我为难,因为这个语法没有确切体现到底怎么回事。假如一个应试者给出这个作为方案,我将用这个作为一个机会去探究他们这么做的基本原 理。假如他们的基本答案是:"我被教着这么做,但从没有想到过为何。"这会给我留下一个坏印象。
第三个方案是用 goto
Loop:
...
goto Loop;
应试者如给出上面的方案,这阐明或者他是一个汇编 语言程序员(这也许是好事)或者他是一个想进入新领域的BASIC/FORTRAN程序员。
数据申明(Data declarations)
5. 用变量a给出下面的定义
a) 一个整型数(An integer)
b)一个指向整型数的指针( A pointer to an integer)
c)一个指向指针的的指针,它指向的指针是指向一个整型数( A pointer to a pointer to an intege)r
d)一个有10个整型数的数组( An array of 10 integers)
e)一个有10个指针的数组,该指针是指向一个整型数的。(An array of 10 pointers to integers)
f)一个指向有10个整型数数组的指针( A pointer to an array of 10 integers)
g)一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer)
h)一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions that take an integer argument and return an integer )
答案是:
a) int a; // An integer
b) int *a; // A pointer to an integer
c) int **a; // A pointer to a pointer to an integer
d) int a[10]; // An array of 10 integers
e) int *a[10]; // An array of 10 pointers to integers
f) int (*a)[10]; // A pointer to an array of 10 integers
g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer
h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer
人们常常声称这里有几个问题是那种要翻一下书才能回答的问题,我同意这种说法。当我写这篇文章时,为了确定语法的正确性,我确实查了一下书。不过当 我被面试的时候,我期望被问到这个问题(或者相近的问题)。因为在被面试的这段时间里,我确定我懂得这个问题的答案。应试者假如不懂得所有的答案(或最少 大部分答案),那么也就没有为这次面试做准备,假如该面试者没有为这次面试做准备,那么他又能为何出准备呢?
Static
6. 核心字static的作用是什么?
这个简单的问题极少有人能回答完全。在C语言中,核心字static有三个明显的作用:
1)在函数体,一个被申明为静态的变量在这一函数被调用过程中维持其值不变。
2)在模块内(但在函数体外),一个被申明为静态的变量能够被模块内所用函数访问,但不能被模块外其他函数访问。它是一个本地的全局变量。
3)在模块内,一个被申明为静态的函数只可被这一模块内的其他函数调用。那就是,这个函数被限制在申明它的模块的本地范围内使用。
大多数应试者能正确回答第一部分,一部分能正确回答第二部分,同是极少的人能懂得第三部分。这是一个应试者的严重的缺陷,因为他显然不懂得本地化数 据和代码范围的好处和重要性。
Const
7.核心字const有什么含意?
我只要一听到被面试者说:"const意味着常数",我就懂得我正在和一个业余者打交道。去年Dan Saks已经在他的文章里完全概括了const的所有使用方法,因此ESP(译者:Embedded Systems Programming)的每一位读者应当非常熟悉const能做什么和不能做什么.假如你从没有读到那篇文章,只要能说出const意味着"只读"就可 以了。尽管这个答案不是完全的答案,但我接收它作为一个正确的答案。(假如你想懂得更详细的答案,仔细读一下Saks的文章吧。)
假如应试者能正 确回答这个问题,我将问他一个附加的问题:
下面的申明都是什么意思?
const int a;
int const a;
const int *a;
int * const a;
int const * a const;
/******/
前两个的作用是同样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可 以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是能够修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常 指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。假如应试者能正确回答这些问题,那么他就给我留下了一个好印象。顺带提一句, 也许你也许会问,虽然不用核心字 const,也还是能很轻易写出功效正确的程序,那么我为何还要如此看重核心字const呢?我也如下的几下理由:
1)核心字const的作用是为给读你代码的人传达非常有用的信息,实际上,申明一个参数为常量是为了告诉了用户这个参数的应用目标。假如你曾花诸多时间清理 其他人留下的垃圾,你就会很快学会感激这点多出的信息。(当然,懂得用const的程序员极少会留下的垃圾让他人来清理的。)
2)通过给优化器某些附加的信息,使用核心字const也许能产生更紧凑的代码。
3)合理地使用核心字const能够使编译器很自然地保护那些不希望被变化的参数,预防其被无意的代码修改。简而言之,这么能够减少bug的出现。
Volatile
8. 核心字volatile有什么含意?并给出三个不一样的例子。
一个定义为volatile的变量是说这变量也许会被意想不到地变化,这 样,编译器就不会去假设这个变量的值了。精准地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在存储器里的备份。 下面是volatile变量的几个例子:
1) 并行设备的硬件存储器(如:状态存储器)
2)一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3) 多线程应用中被几个任务共享的变量
回答不出这个问题的人是不会被雇佣的。我以为这是辨别C程序员和嵌入式系统程序员的最基本的问题。搞嵌入式的家伙们常常同硬件、中断、RTOS等等 打交道,所有这些都要求用到volatile变量。不懂得volatile的内容将会带来灾难。
假设被面试者正确地回答了这是问题(嗯,怀疑是否 会是这么),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。
1)一个参数既能够是const还能够是volatile吗?解释为何。
2); 一个指针能够是volatile 吗?解释为何。
3); 下面的函数有什么错误:
int square(volatile int *ptr)
{
return *ptr * *ptr;
}
下面是答案:
1)是的。一个例子是只读的状态存储器。它是volatile因为它也许被意想不到地变化。它是const因为程序不应当试图 去修改它。
2); 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。
3)这段代码有点变态。这段代码的目标是用来返指针*ptr指向值的平方,不过,因为*ptr指向一个volatile型参数,编译器将产生类似下面的代码:
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}
因为*ptr的值也许被意想不到地该变,因此a和b也许是不一样的。成果,这段代码也许返不是你所期望的平方值!正确的代码如下:
long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}
位操作(Bit manipulation)
9. 嵌入式系统总是要用户对变量或存储器进行位操作。给定一个整型变量a,写两段代码,第一个设置a的bit 3,第二个清除a 的bit 3。在以上两个操作中,要保持其他位不变。
对这个问题有三种基本的反应
1)不懂得怎样下手。该被面者从没做过任何嵌入式系统的工作。
2)用bit fields。Bit fields是被扔到C语言死角的东西,它确保你的代码在不一样编译器之间是不可移植的,同时也确保了的你的代码是不可重用的。我最近不幸看到Infineon为其较复杂的通信芯片写的驱动程序,它用到了bit fields因此完全对我无用,因为我的编译器用其他的方式来实现bit fields的。从道德讲:永远不要让一个非嵌入式的家伙粘实际硬件的边。
3) 用 #defines 和 bit masks操作。这是一个有极高可移植性的措施,是应当被用到的措施。最佳的处理方案如下:
#define BIT3 (0x1 << 3)
static int a;
void set_bit3(void)
{
a |= BIT3;
}
void clear_bit3(void)
{
a &= ~BIT3;
}
某些人喜欢为设置和清除值而定义一个掩码同时定义某些阐明常数,这也是能够接收的。我希望看到几个要点:阐明常数、|=和&=~操作。
访问固定的内存位置(Accessing fixed memory locations)
10.嵌入式系统常常具备要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个 纯粹的ANSI编译器。写代码去完成这一任务。
这一问题测试你是否懂得为了访问一绝对地址把一个整型数强制转换(typecast)为一指针是合 法的。这一问题的实现方式伴随个人格调不一样而不一样。经典的类似代码如下:
int *ptr;
ptr = (int *)0x67a9;
*ptr = 0xaa55;
A more obscure approach is:
一个较艰涩的措施是:
*(int * const)(0x67a9) = 0xaa55;
虽然你的品味更接近第二种方案,但我提议你在面试时使用第一个方案。
中断(Interrupts)
11. 中断是嵌入式系统中重要的组成部分,这导致了诸多编译开发商提供一个扩展—让标准C支持中断。具代表事实是,产生了一个新的核心字__interrupt。下面的代码就使用了__interrupt核心字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。
__interrupt double compute_area (double radius)
{
double area = PI * radius * radius;
printf("\nArea = %f", area);
return area;
}
这个函数有太多的错误了,以至让人不知从何说起了:
1)ISR 不能返回一个值。假如你不懂这个,那么你不会被雇用的。
2) ISR 不能传递参数。假如你没有看到这一点,你被雇用的机会等同第一项。
3)在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额处的存储器入栈,有些处理器/编译器就是不允许在ISR中做浮点运算。此 外,ISR应当是短而有效率的,在ISR中做浮点运算是不明智的。
4)与第三点一脉相承,printf()常常有重入和性能上的问题。假如你丢掉了第三和第四点,我不会太为难你的。不用说,假如你能得到后两点,那么你的被雇 用前景越来越光明了。
代码例子(Code examples)
12 . 下面的代码输出是什么,为何?
void foo(void)
{
unsigned int a = 6;
int b = -20;
(a+b > 6) ? puts("> 6") : puts("<= 6");
}
这个问题测试你是否懂得C语言 中的整数自动转换标准,我发觉有些开发者懂得极少这些东西。无论怎样,这无符号整型问题的答案是输出是">6"。原因是当体现式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,因此该体现式 计算出的成果不小于6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。假如你答错了这个问题,你也就到了得不到这份工作的边缘。
13. 评价下面的代码片断:
unsigned int zero = 0;
unsigned int compzero = 0xFFFF;
/*1's complement of zero */
对于一个int型不是16位的处理器为说,上面的代码是不正确的。应编写如下:
unsigned int compzero = ~0;
这一问题真正能揭露出应试者是否懂得处理器字长的重要性。在我的经验里,好的嵌入式程序员非常准确地明白硬件的细节和它的局限,然而PC机程序往往 把硬件作为一个无法防止的烦恼。
到了这个阶段,应试者或者完全垂头丧气了或者信心满满志在必得。假如显然应试者不是很好,那么这个测试就在这里结 束了。但假如显然应试者做得不错,那么我就扔出下面的追加问题,这些问题是比较难的,我想仅仅非常优秀的应试者能做得不错。提出这些问题,我希望更多看到 应试者应付问题的措施,而不是答案。无论怎样,你就当是这个娱乐吧...
动态内存分派(Dynamic memory allocation)
14.尽管不像非嵌入式计算机那么常见,嵌入式系统还是有从堆(heap)中动态分派内存的过程的。那么嵌入式系统中,动态分派内存也许发生的问题是什么?
这 里,我期望应试者能提到内存碎片,碎片搜集的问题,变量的持行时间等等。这个主题已经在ESP杂志中被广泛地讨论过了(重要是 P.J. Plauger, 他的解释远远超出我这里能提到的任何解释),所有回过头看一下这些杂志吧!让应试者进入一个虚假的安全感觉后,我拿出这么一个小节目:
下 面的代码片段的输出是什么,为何?
char *ptr;
if ((ptr = (char *)malloc(0)) == NULL)
puts("Got a null pointer");
else
puts("Got a valid pointer");
这是一个有趣的问题。最近在我的一个同事不经意把0值传给了函数malloc,得到了一个合法的指针之后,我才想到这个问题。这就是上面的代码,该 代码的输出是"Got a valid pointer"。我用这个来开始讨论这么的一问题,看看被面试者是否想到库例程这么做是正确。得到正确的答案当然重要,但处理问题的措施和你做决定的基 本原理更重要些。
Typedef
15 Typedef在C语言中频繁用以申明一个已经存在的数据类型的同义字。也能够用预处理器做类似的事。例如,思考一下下面的例子:
#define dPS struct s *
typedef struct s * tPS;
以上两种情况的意图都是要定义dPS 和 tPS 作为一个指向结构s指针。哪种措施愈加好呢?(假如有的话)为何?
这是一个非常微妙的问 题,任何人答对这个问题(合法的原因)是应当被恭喜的。答案是:typedef愈加好。思考下面的例子:
dPS p1,p2;
tPS p3,p4;
第一个扩展为
struct s * p1, p2;
.
上面的代码定义p1为一个指向结构的指,p2为一个实际的结构,这也许不是你想要的。第二 个例子正确地定义了p3 和p4 两个指针。艰涩的语法
16 . C语言同意某些令人震惊的结构,下面的结构是合法的吗,假如是它做些什么?
int a = 5, b = 7, c;
c = a+++b;
这个问题将做为这个测验的一个愉快的结尾。无论你相不相信,上面的例子是完全合乎语法的。问题是编译器怎样处理它?水平不高的编译作者实际上会争论 这个问题,依照最处理标准,编译器应当能处理尽也许所有合法的使用方法。因此,上面的代码被处理成:
c = a++ + b;
因此, 这段代码持行后a = 6, b = 7, c = 12。
假如你懂得答案,或猜出正确答案,做得好。假如你不懂得答案,我也不把 这个当作问题。我发觉这个问题的最大好处是这是一个有关代码编写格调,代码的可读性,代码的可修改性的好的话题。
华为笔试题
1.写出判断ABCD四个体现式的是否正确, 若正确, 写出通过体现式中 a的值(3分)
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 的值(5分).
char str[] =“”
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)17 (2)4 (3) 4 (4)4(5)4
3. 回答下面的问题. (4分)
(1).头文献中的 ifndef/define/endif 干什么用?预处理
答:预防头文献 被重复引用
(2). #include 和 #include “filename.h” 有什么区分?
答:前者用来包括开发环境提供的 库头文献,后者用来包括自己编写的头文献。
(3).在C++ 程序中调用被 C 编译器编译后的函数,为何要加 extern “C”申明?
答: 函数和变量被C++编译后在符号库中的名字与C语言的不一样,被extern "C"修饰的变
量和函数是按照C语言方式编译和连接的。因为编译后的 名字不一样,C++程序不能直接调
用C 函数。C++提供了一个C 连接互换指定符号extern“C”来处理这个问题。
(4). switch()中不允许的数据类型是?
答:实型
4. 回答下面的问题(6分)
(1).Void GetMemory(char **p, int num){
*p = (char *)malloc(num);
}
void Test(void){
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
}
请问运行Test函数会有什么样的成果?
答:输出“hello”
(2). void Test(void){
char *str = (char *) malloc(100);
strcpy(str, “hello”);
free(str);
if(str != NULL){
strcpy(str, “world”);
printf(str);
}
}
请问运行Test函数会有什么样的成果?
答:输出“world”
(3). char *GetMemory(void){
char p[] = "hello world";
return p;
}
void Test(void){
char *str = NULL;
str = GetMemory();
printf(str);
}
请问运行Test 函数会有什么样的成果?
答: 无效的指针,输出不确定
5. 编写strcat函数(6分)
已知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.MFC中CString是类型安全类么?
答:不是,其他数据类型转换到CString能够使用CString的组员函数Format来 转换
7.C++中为何用模板类。
答:(1)可用来创建动态增加和减小的数据结构
(2)它是类型无关的,因此具备很高的可复用性。
(3) 它在编译时而不是运行时检查数据类型,确保了类型安全
(4)它是平台无关的,可移植性
(5)可用于基本数据类型
8.CSingleLock是干什么的。
答:同时多个线程对一个数据类的同时访问
9.NEWTEXTMETRIC 是什么。
答:物理字体结构,用来设置字体的高宽大小
10.程序什么时候应当使用线程,什么时候单线程效率高。
答:1.耗时的操作使用线程,提升应用程序响应
2.并行操作时使用线程, 如C/S架构的服务器端并发线程响应用户的祈求。
3.多CPU系统中,使用线程提升CPU利用率
4.改进程序结构。一个既长又复杂的进程 能够考虑分为多个线程,成为几个独立或半独
立的运行部分,这么的程序会利于了解和修改。
其他情况都使用单线程。
11.Windows是内核级线程么。
答:见下一题
12.Linux有内核级线程么。
答:线程一般被定义为一个进程中代码的不一样执行路线。从实现方式上划分,线程有两
种类型:“用户 级线程”和“内核级线程”。 用户线程指不需要内核支持而在用户程序
中实现的线程,其不依赖于操作系统核心,应用进程利用线程库提供创建、同时、 调度
和管理线程的函数来控制用户线程。这种线程甚至在象 DOS 这么的操作系统中也可实现
,但线程的调度需要用户程序完成,这有些类似Windows 3.x 的协作式多任务。另外一
种则需要内核的参加,由内核完成线程的调度。其依赖于操作系统核心,由内核的内部
需求 进行创建和撤消,这两种模型各有其好处和缺陷。用户线程不需要额外的内核开支
,并且用户态线程的实现方式能够被定制或修改以适应特殊应用的要求, 不过当一个线
程因 I/O 而处在等候状态时,整个进程就会被调度程序切换为等候状态,其他线程得不
到运行的机会;而内核线程则没有各个 限制,有利于发挥多处理器的并发优势,但却占
用了更多的系统开支。
Windows NT和OS/2支持内核线程。Linux支持内核级的多线程
13.C++中什么数据分派在栈或堆中,New分派数据是在近堆还是远堆中?
答:栈:存储局部变量,函数调用参数,函数返回值,函数返回地址。由系统管理
堆: 程序运行时动态申请,new 和 malloc申请的内存就在堆上
14.使用线程是怎样预防出现大的波峰。
答:意思是怎样预防同时产生大量的线程,措施是使用线程池,线程池具备能够同时提
高调度效 率和限制资源使用的好处,线程池中的线程达成最大数时,其他线程就会排队
等候。
15函数模板与类模板有什么区分?
答:函数模板的实例化是由编译程序在处理函数调用时自动完成的,而类模板的实例化
必须由程序员在 程序中显式地指定。
16一般数据库若出现日志满了,会出现什么情况,是否还能使用?
答:只能执行查询等读操作,不能执行更改,备份等写操作,原因是任何写操作 都要记
录日志。也就是说基本上处在不能使用的状态。
17 SQL Server是否支持行级锁,有什么好处?
答:支持,设置封锁机制重要是为了对并发操作进行控制,对干扰进行封锁,确保数据
的 一致性和准确性,行级封锁确保在用户取得被更新的行到该行进行更新这段时间内不
被其他用户所修改。因而行级锁即可确保数据的一致性又能提升数据操 作的迸发性。
18假如数据库满了会出现什么情况,是否还能使用?
答:见16
19 有关内存对齐的问题以及sizof()的输出
答:编译器自动对齐的原因:为了提升程序的性能,数据结构(尤其是栈)应当尽也许
地 在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问
;然而,对齐的内存访问仅需要一次访问。
20 int i=10, j=10, k=3; k*=i+j; k最后的值是?
答:60,此题考查优先级,实际写成:k*=(i+j);,赋值运算符优先级最低
21.对数据库的一张表进行操作,同时要对另一张表进行操作,怎样实现?
答:将操作多个表的操作放入到事务中进行处理
22.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状态,完成三次握手。
23.ICMP是什么协议,处在哪一层?
答:Internet控制报文协议,处在网络层(IP层)
24.触发器怎么工作的?
答:触发器重要是通过事件进行触发而被执行的,当对某一表进行诸如UPDATE、 INSERT
、DELETE 这些操作时,数据库就会自动执行触发器所定义的SQL 语句,从而确保对数
据的处理必须符合由这些SQL 语句所定义的规则。
25.winsock建立连接的重要实现步骤?
答:服务器端:socker()建立套接字,绑定(bind)并监听(listen),用accept()
等候客户端连接。
客户端:socker()建立套接字,连接(connect)服务器,连接上后使用send()和recv(
),在套接字上写读数据,直至数据互换完成,closesocket()关闭套接字。
服务器端:accept()发觉有客户端 连接,建立一个新的套接字,自身重新开始等候连
接。该新产生的套接字使用send()和recv()写读数据,直至数据互换完 毕,closesock
et()关闭套接字。
26.动态连接库的两种方式?
答:调用一个DLL中的函数有两种措施:
1.载入时动态链接(load-time dynamic linking),模块非常明确调用某个导出函数
,使得他们就像本地函数同样。这需要链接时链接那些函数所在DLL的导入库,导入库向
系 统提供了载入DLL时所需的信息及DLL函数定位。
2.运行时动态链接(run-time dynamic linking),运行时能够通过LoadLibrary或Loa
dLibraryEx函数载入DLL。DLL载入后,模块能够通过调用GetProcAddress获取DLL函数的
出口地址,然后就能够通过返回的函数指针调用DLL函数了。如此即可防止导入库文献了
。
27.IP组播有那些好处?
答:Internet上产生的许多新的应用,尤其是高带宽的多媒体应用,带来了带宽的急剧
消耗和网络拥 挤问题。组播是一个允许一个或多个发送者(组播源)发送单一的数据包
到多个接收者(一次的,同时的)的网络技术。组播能够大大的节约网络带宽,因 为无
论有多少个目标地址,在整个网络的任何一条链路上只传送单一的数据包。因此说组播
技术的核心就是针对怎样节约网络资源的前提下确保服 务质量。
1.static有什么用途?(请最少阐明两种)
1)在函数体,一个被申明为静态的变量在这一函数被调用过程中维持其值不变。
2) 在模块内(但在函数体外),一个被申明为静态的变量能够被模块内所用函数访问,但不能被模块外其他函数访问。它是一个本地的全局变量。
3) 在模块内,一个被申明为静态的函数只可被这一模块内的其他函数调用。那就是,这个函数被限制在申明它的模块的本地范围内使用
2.引用与指针有什么区分?
1) 引用必须被初始化,指针无须。
2)引用初始化以后不能被变化,指针能够变化所指的对象。
3) 不存在指向空值的引用,不过存在指向空值的指针。
3.描述实时系统的基本特性
在特定期间内完成特定的任务,实时性与可靠性。
4.全局变量和局部变量在内存中是否有区分?假如有,是什么区分?
全局变量储存在静态数据库,局部变量在堆栈。
5.什么是平衡二叉树?
左右子树都是平衡二叉树 且左右子树的深度差值的绝对值小于1。
6.堆栈溢出一般是由什么原因导致的?
没有回收垃圾资源。
7.什么函数不能申明为虚函数?
constructor函数不能申明为虚函数。
8.冒泡排序算法的时间复杂度是什么?
时间复杂度是O(n^2)。
9.写出float x 与“零值”比较的if语句。
if(x>0.000001&&x<-0.000001)
10.Internet采取哪种网络协议?该协议的重要层次结构?
Tcp/Ip协议
重要层次结构为: 应用层/传输层/网络层/数据链路层/物理层。
11.Internet物理地址和IP地址转换采取什么协议?
ARP (Address Resolution Protocol)(地址解析協議)
12.IP地址的编码分为哪俩部分?
IP地址由两部分组成,网络号和主机号。不过是要和“子网掩码”按位与上之后才能辨别哪些是网络位哪些是主机位。
13.用户输入M,N值,从1至N开始次序循环数数,每数到M输出该数值,直至所有输出。写出C程序。
循环链表,用取余操作做
14.不能做switch()的参数类型是:
switch的参数不能为实型。
華為
1、局部变量能否和全局变量重名?
答:能,局部会屏蔽全局。要用全局变量,需要使用"::"
局部变量能够与 全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。对于有些编译器而言,在同一个函数内能够定义多个同名的局部变量,比 如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内。
2、怎样引用一个已经定义过的全局变量?
答:extern
能够用引用头文献的方式,也能够用extern核心字,假如用引用头文献方式来引用某个在头文献中申明的全局变理,假定你将那个变写错了,那么在编译期间 会报错,假如你用extern方式引用时,假定你犯了同样的错误,那么在编译期间不会报错,而在连接期间报错。
3、全局变量可不能够定义在可被多个.C文献包括的头文献中?为何?
答:能够,在不一样的C文献中以static形式来申明同名全局变量。
能够在不一样的C文献中申明同名的全局变量,前提是其中只能有一个C文献中对此变量赋初值,此时连接不会犯错。
展开阅读全文