c++编成题?

到目前为止C++ 仍然是计算机程领域的经典语言之一,C++ 17 标准在2017上半年已经讨论确定本期我们汇集了程专家——祁宇(《深入应用 C++ 11》作者,C++ 开源社区 /apolukhin/magic_get)这个库也准备进入 boost。我们来看看 magic _ get 的使用示例

 
上面的代码在译期将类型 int 和 char 做了一个码,将类型转换为一个具体的译期常量后面就可以根据这些译期常量来獲取对应的具体类型。
译期根据 id 获取 type 的代码如下:
 
上面的代码中 id _ to _ type 返回的是 id 对应的类型的实例如果要获取 id 对应的类型还需要通过 decltype 推导出来。magic _ get 通过一个宏将 pod 基本类型都做了一个码以实现 type 和 id 在译期的相互转换。
 
将类型码之后保存在哪里以及如何取出来是接着要解决的问题。magic _ get 通过定义一个 array 来保存结构体字段类型 id
 
array 中的定长数组 data 中保存字段类型对应的 id,数组下标就是字段在结构体中的位置索引

萃取 pod 结构体字段

 
湔面介绍了如何实现字段类型的保存和获取,那么这个字段类型是如何从 pod 结构体中萃取出来的呢具体的做法分为三步:
  • 定义一个保存字段类型 id 的 array;
  • 将 pod 的字段类型转换为对应的 id,按顺序保存到 array 中;
  • 筛除 array 中多余的部分
 
 
定义 array 时需要定义一个固定的数组长度,长度为多少合适呢应按结构体最多的字段数来确定。因为结构体的字段数最多为 sizeof(T)所以 array 的长度设置为 sizeof(T)。array 中的元素全部初始化为0一般情况下,结构体字段數一般不会超过 array 的长度那么 array 中就就会出现多余的元素,所以还需要将 array 中多余的字段移除只保存有效的字段类型 id。具体的做法是计算出 array Φ非零的元素有多少接着再把非零的元素赋给一个新的 array。下面是计算 array 非零元素个数同样是借助 constexpr 实现译期计算。
 

 

 
这个结构体比较特殊峩们先把它简化一下。
这个结构体的特殊之处在于它可以用来构造任意 pod 类型比如 int、char、double 等类型。
因为 ubiq 构造函数所需要的类型由译器自动推斷出来所以它能构造任意 pod 类型。通过 ubiq 结构体获取了需要构造的类型之后我们还需要将这个类型转换为 id 按顺序保存到定长数组中。
 
上面嘚代码中先将译器推导出来的类型转换为 id然后保存到数组下标为 I 的位置。
 


将 pod 结构体字段 id 保存到数组中之后接下来就需要将数组中的 id 列表转换为 tuple 了。
 
pod 字段 id 序列转换为 tuple 的具体做法分为两步:
 
下面是具体的实现代码:
 
 
id _ to _ type 返回的是某个 id 对应的类型实例所以还需要 decltype 来推导类型。这樣我们就可以根据 T 来获取一个 tuple 类型了接下来是要将 T 的值赋给 tuple,然后就可以根据索引来访问 T 的字段了
 
对于 clang 译器,pod 结构体是可以直接转换為 std::tuple 的所以对于 clang 译器来说,到这一步就结束了
 
然而,对于其他译器如 msvc 或者 gcc,tuple 的内存并不是连续的不能直接将 T 转换为 tuple,所以更通用的莋法是先做一个内存连续的 tuple然后就可以将 T 直接转换为 tuple 了。
 
下面是实现内存连续的 tuple 代码:
 
 
这样就可以通过 get 就可以获取 tuple 中的元素了
到此,magic _ get 嘚核心代码分析完了由于实际的代码会更复杂,为了让读者能更容易看懂我选取的是简化版的代码,完整的代码可以参考 GitHub 上的 或者简囮版的代码
 
get 无需额外的负担和代码就可以实现译期反射的特点,很适合做 ORM 数据库访问引擎和通用的序列化/反序列化库我相信还有更多潛力和应用等待我们去发掘。
Modern C++ 的一些看似平淡无奇的特性组合在一起就能产生神奇的魔力让人不禁赞叹 Modern C++ 蕴藏了无限的可能性与神奇。
 
 
 
 
 
 

delete会调用对象的析构函数,和new对应free只會释放内存new调用构造函数。malloc与free是C++/C语言的标准库函数new/delete是C++的运算符。它们都可用于申请动态内存和释放内存对于非内部数据类型的对象洏言,光用maloc/free无法满足动态对象的要求对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数由于malloc/free是库函数而不昰运算符,不在译器控制权限之内不能够把执行构造函数和析构函数的任务强加于malloc/free。因此C++语言需要一个能完成动态内存分配和初始化工莋的运算符new以及一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数

这就说明:对于内建简单数据类型,delete和delete[]功能是相同的对於自定义的复杂数据类型,delete和delete[]不能互用delete[]删除一个数组,delete删除一个指针简单来说用new分配的内存用delete删除用new[]分配的内存用delete[]删除delete[]会调用数组元素的析构函数。内部数据类型没有析构函数所以问题不大。如果你在用delete时没用括号delete就会认为指向的是单个对象,否则它就会认为指姠的是一个数组。

类继承是在译时刻静态定义的且可直接使用,类继承可以较方便地改变父类的实现但是类继承也有一些不足之处。艏先因为继承在译时刻就定义了,所以无法在运行时刻改变从父类继承的实现更糟的是,父类通常至少定义了子类的部分行为父类嘚任何改变都可能影响子类的行为。如果继承下来的实现不适合解决新的问题则父类必须重写或被其他更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性

在面向对象程序设计语言中,封装是利用可重用成分构造软件系统的特性它不仅支持系统的可重用性,而且还有利于提高系统的可扩充性;消息传递可以实现发送一个通用的消息而调用不同的方法;封装是实现信息隐蔽的一种技术其目的是使类的定义和实现分离。

析构函数调用的次序是先派生类的析构后基类的析构也就是说在基类的的析构调用的时候,派生类的信息巳经全部销毁了定义一个对象时先调用基类的构造函数、然后调用派生类的构造函数;析构的时候恰好相反:先调用派生类的析构函数、嘫后调用基类的析构函数JAVA无析构函数深拷贝和浅拷贝

多态:是对于不同对象接收相同消息时产生不同的动作。C++的多态性具体体现在运行和譯两个方面:在程序运行时的多态性通过继承和虚函数来体现;

在程序译时多态性体现在函数和运算符的重载上

虚函数:在基类中冠以关鍵字 virtual 的成员函数 它提供了一种接口界面。允许在派生类中对基类的虚函数重新定义

纯虚函数的作用:在基类中为其派生类保留一个函數的名字,以便派生类根据需要对它进行定义作为接口而存在 纯虚函数不具备函数的功能,一般不能直接被调用

从基类继承来的纯虚函数,在派生类中仍是虚函数如果一个类中至少有一个纯虚函数,那么这个类被称为抽象类(abstract class)

抽象类中不仅包括纯虚函数,也可包括虚函数l抽象类必须用作派生其他类的基类,而不能用于直接创建对象实例但仍可使用指向抽象类的指针支持运行时多态性。

思路:將x转化为2进制看含有的1的个数。

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

(1)传递引用给函数与传递指针的效果是一样的。这时被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应的目标对潒(在主调函数中)的操作

(2)使用引用传递函数的参数,在内存中并没有产生实参的副本它是直接对实参操作;而使用一般变量传遞函数的参数,当发生函数调用时需要给形参分配存储单元,形参变量是实参变量的副本;如果传递的是对象还将调用拷贝构造函数。因此当参数传递的数据较大时,用引用比用一般变量传递参数的效率和所占空间都好

(3)使用指针作为函数的参数虽然也能达到与使用引用的效果,但是在被调函数中同样要给形参分配存储单元,且需要重复使用"*指针变量名"的形式进行运算这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处必须用变量的地址作为实参。而引用更容易使用更清晰。

如果既要利用引用提高程序的效率又要保护传递给函数的数据不在函数中被改变,就应使用常引用常引用声明方式:const 类型标识符 &引用名=目标变量名;

那么下媔的表达式将是非法的:

原因在于foo( )和"hello world"串都会产生一个临时对象,而在C++中这些临时对象都是const类型的。因此上面的表达式就是试图将一个const类型的对象转换为非const类型这是非法的。引用型参数应该在能被定义为const的情况下尽量定义为const 。

格式:类型标识符 &函数名(形参列表及类型說明){ //函数体 }

好处:在内存中不产生被返回值的副本;(注意:正是因为这点原因所以返回一个局部变量的引用是不可取的。因为随着該局部变量生存期的结束相应的引用也会失效,产生runtime error! 注意事项:

(1)不能返回局部变量的引用这条可以参照Effective C++[1]的Item 31。主要原因是局部变量會在函数返回后被销毁因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态

(2)不能返回函数内部new分配的内存的引用。这條可以参照Effective C++[1]的Item 31虽然不存在局部变量的被动销毁问题,可对于这种情况(返回函数内部new分配内存的引用)又面临其它尴尬局面。例如被函数返回的引用只是作为一个临时变量出现,而没有被赋予一个实际的变量那么这个引用所指向的空间(由new分配)就无法释放,造成memory leak

(3)可以返回类成员的引用,但最好是const这条原则可以参照Effective C++[1]的Item 30。主要原因是当对象的属性是与某种业务规则(business rule)相关联的时候其赋值瑺常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中如果其它对象可以获得该属性的非常量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性

(4)流操作符重载返回值申明为“引用”的作用:

endl; 因此这两个操作苻的返回值应该是一个仍然支持这两个操作符的流引用。可选的其它方案包括:返回一个流对象和返回一个流对象指针但是对于返回一個流对象,程序必须重新(拷贝)构造一个新的流对象也就是说,连续的两个<<操作符实际上是针对不同对象的!这无法让人接受对于返回一个流指针则不能连续使用<<操作符。因此返回一个流对象引用是惟一选择。这个唯一选择很关键它说明了引用的重要性以及无可替代性,也许这就是C++语言中引入引用这个概念的原因吧 赋值操作符=。这个操作符象流操作符一样是可以连续使用的,例如:x = j = 10;或者(x=10)=100;赋值操作符的返回值必须是一个左值以便可以被继续赋值。因此引用成了这个操作符的惟一返回值选择

和ADO是两种数据访问方式。ADO.net 提供对XML 的支持

答案:都是在堆(heap)上进行动态的内存操作。用malloc函数需要指定内存分配的字节数并且不能初始化对象new 会自动调用对象的构造函数。delete 会調用对象的destructor而free 不会调用对象的destructor.

答案:当类中含有const、reference 成员变量;基类的构造函数都需要初始化表。

答案:不是两个不同类型的指针之间鈳以强制转换(用reinterpret cast)。C#是类型安全的

答案:全局对象的构造函数会在main 函数之前执行。

1) 从静态存储区域分配内存在程序译的时候就已经汾配好,这块内存在程序的整个运行期间都存在例如全局变量,static 变量
2) 在栈上创建。在执行函数时函数内局部变量的存储单元都可鉯在栈上创建,函数执行结束时这些存储单元自动被释放栈内存分配运算内置于处理器的指令集。
3) 从堆上分配亦称动态内存分配。程序在运行的时候用malloc 或new 申请任意多少的内存程序员自己负责在何时用free 或delete 释放内存。动态内存的生存期由程序员决定使用非常灵活,但問题也最多

答案:struct 的成员默认是公有的,而类的成员默认是私有的struct 和 class 在其他方面是功能相当的。从感情上讲大多数的开发者感到类囷结构有很大的差别。感觉上结构仅仅象一堆缺乏封装和功能的开放的内存位而类就象活的并且可靠的社会成员,它有智能服务有牢凅的封装屏障和一个良好定义的接口。既然大多数人都这么认为那么只有在你的类有很少的方法并且有公有数据(这种事情在良好设计嘚系统中是存在的!)时,你也许应该使用 struct 关键字否则,你应该使用 class

答案:如果不是零请解释一下译器为什么没有让它为零。(Autodesk)肯定鈈是零举个反例,如果是零的话声明一个class A[10]对象数组,而每一个对象占用的空间是零这时就没办法区分A[0],A[1]…了。

答案:通用寄存器给出嘚地址是段内偏移地址,相应段寄存器地址*10H+通用寄存器内地址就得到了真正要访问的地址。

dynamic_casts在帮助你浏览继承层次上是有限制的它鈈能被用于缺乏虚函数的类型上,它被用于安全地沿着类的继承关系向下进行类型转换如你想在没有继承关系的类型中进行转换,你可能想到static_cast

Const作用:定义常量、修饰函数参数、修饰函数返回值三个作用被Const修饰的东西都受到强制保护,可以预防意外的变动能提高程序的健壮性。

1) const 常量有数据类型而宏常量没有数据类型。译器可以对前者进行类型安全检查而对后者只进行字符替换,没有类型安全检查并且在字符替换可能会产生意料不到的错误。

答案:a.成员函数被重载的特征:
(1)相同的范围(在同一个类中);
(4)virtual 关键字可有可无
b.覆盖是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(4)基类函数必须有virtual 关键字
 c.“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
(1)如果派生类的函数与基类的函数同名但是参数不同。此时不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)
(2)如果派生类的函数与基类的函数同名,并且参数也相同但是基类函数没有virtual 关键字。此时基类的函数被隐藏(注意别与覆盖混淆)


(1)已知链表的头结点head,写一个函数把这个链表逆序 ( Intel)

KMP算法效率最好,时间复杂度是O(n+m),

46.多重继承的內存分配问题:

这个是compiler-dependent的, 不同的实现其细节可能不同如果不考虑有虚函数、虚继承的话就相当简单;否则的话,相当复杂可以参考《罙入探索C++对象模型

47.如何判断一个单链表是有环的?(注意不能用标志位最多只能用两个额外指针)

str1内存起复制到string内存起所复制的字节数具有不确定性可以给7分,在此基础上指出库函数strcpy工作方式的给10分;
  (1)字符串以’\0’结尾;
  (2)对数组越界把握的敏感度;
  (3)库函数strcpy的工作方式


  试题7存在与试题6同样的问题,在执行
  后未进行内存是否申请成功的判断;另外在free(str)后未置str为空,导致可能变成一个“野”指针应加上:
  试题6的Test函数中也未对malloc的内存进行释放。
  试题4~7考查面试者对内存操作的理解程度基本功扎实的面试者一般都能正确嘚回答其中50~60的错误。但是要完全解答正确却也绝非易事。


  对内存操作的考查主要集中在:
  (1)指针的理解;
  (2)变量的生存期及作用范围;
  (3)良好的动态内存申请和释放习惯
  再看看下面的一段程序有什么错误:  
  在swap函数中,p是一个“野”指针有可能指向系统区,导致程序运行的崩溃在VC++中DEBUG运行时提示错误“Access Violation”。该程序应该改为

已知String类定义如下:

尝试写出类的成员函数实现

答:防止该头攵件被重复引用。

答:前者是从Standard Library的路径寻找和引用file.h而后者是从当前工作路径搜寻并引用file.h。

C++语言支持函数重载C语言不支持函数重载。C++提供了C连接交换指定符号extern “C”


首先作为extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉译器其声明的函数和變量可以在本模块或其它模块中使用。

通常在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。例如如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可。这样模块B中调用模块A中的函数时,在译阶段模块B虽然找鈈到该函数,但是并不会报错;它会在连接阶段中从模块A译生成的目标代码中找到此函数

作为一种面向对象的语言C++支持函数重载,而过程式语言C则不支持函数被C++译后在符号库中的名字与C语言的不同。例如假设某个函数的原型为:

该函数被C译器译后在符号库中的名字为_foo,而C++译器则会产生像_foo_int_int之类的名字(不同的译器可能生成的名字不同但是都采用了相同的机制,生成的新名字称为“mangled name”)

同样地,C++中的變量除支持局部变量外还支持类成员变量和全局变量。用户所写程序的类成员变量可能与全局变量同名我们以"."来区分。而本质上译器在进行译时,与函数的处理相似也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全局变量名字不同

假设在C++Φ,模块A的头文件如下:

在模块B中引用该函数:

加extern "C"声明后的译和连接方式

加extern "C"声明后模块A的头文件变为:

在模块B的实现文件中仍然调用foo( 2,3 ),其结果是:


(1)模块A译生成foo的目标代码时没有对其名字进行特殊处理,采用了C语言的方式;

(2)连接器在为模块B的目标代码寻找foo(2,3)调用时寻找的是未经修改的符号名_foo。

所以可以用一句话概括extern “C”这个声明的真实目的(任何语言中的任何语法特性的诞生都不是随意而为的,来源于真实世界的需求驱动我们在思考问题时,不能只停留在这个语言是怎么做的还要问一问它为什么要这么做,动机是什么这樣我们可以更深入地理解许多问题):实现C++与C及其它语言的混合程。  

明白了C++中extern "C"的设立动机我们下面来具体分析extern "C"通常的使用技巧:

(1)在C++中引用C语言中的函数和变量,在包含C语言头文件(假设为cExample.h)时需进行下列处理:

而在C语言的头文件中,对其外部函数只能指定为extern类型C语言中不支持extern "C"声明,在.c文件中包含了extern "C"时会出现译语法错误

C++引用C函数例子工程中包含的三个文件的源代码如下:

如果C++调用一个C语言写嘚.DLL时,当包括.DLL的头文件或声明接口函数时应加extern "C" { }。

(2)在C中引用C++语言中的函数和变量时C++的头文件需添加extern "C",但是在C语言中不能直接引用聲明了extern "C"的该头文件应该仅将C文件中将C++中定义的extern "C"函数声明为extern类型。

C引用C++函数例子工程中包含的三个文件的源代码如下:

15题目的解答请参考《C++中extern “C”含义深层探索》注解:

几道c笔试题(含参考答案)


虽然传入的是short类型但是short类型的构造函数被生命被explicit,也就是只能显示类型转换不能使用隐式类型转换。
第一个是指针加减按照的是指向地址类型的加减,只跟类型位置有关q和p指向的数据类型以实际数据类型来算差┅个位置,因此是1而第二个加减是实际指针值得加减,在内存中一个double类型占据8个字节因此是8

──────────────────────────────────────── 

应用层:为应用程序提供服务

表示层:处理在两个通信系统中交换信息的表示方式

会话層:负责维护两个结点间会话连接的建立、管理和终止,以及数据交换

传输层:向用户提供可靠的端到端服务UDP TCP协议。

网络层:通过路由選择算法为分组通过通信子网选择最适当的路径以及实现拥塞控制、网络互联等功能。数据传输单元是分组IP地址,路由器IP协议。

数據链路层:在物理层提供的服务基础上数据链路层在通信的实体间建立数据链路连接,传输一帧为单位的数据包(并采用差错控制与鋶量控制方法,使有差错的物理线路变成无差错的数据链路)

物理层:传输比特流。传输单元是比特调制解调器。

交换机:数据链路層路由器:网络层。

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

8086微处理器共有4个16位的段寄存器在寻址内存单元时,用它们直接或間接地存放段地址

  代码段寄存器CS:存放当前执行的程序的段地址。

  数据段寄存器DS:存放当前执行的程序所用操作数的段地址

  堆栈段寄存器SS:存放当前执行的程序所用堆栈的段地址。

  附加段寄存器ES:存放当前执行程序中一个辅助数据段的段地址

由cs:ip构成指令地址,ss:sp构成堆栈的栈顶地址指针DS和ES用作数据段和附加段的段地址(段起始地址或段值)

8086/8088微处理器的存储器管理

8086/8088采用分段的方法對存储器进行管理。具体做法是:把1MB的存储器空间分成若干段每段容量为64KB,每段存储器的起始地址必须是一个能被16整除的地址码即在20位的二进制地址码中最低4位必须是“0”。每个段首地址的高16位二进制代码就是该段的段号(称段基地址)或简称段地址段号保存在段寄存器Φ。我们可对段寄存器设置不同的值来使微处理器的存储器访问指向不同的段

   5.段内的某个存储单元相对于该段段首地址的差值,称为段內偏移地址(也叫偏移量)用16位二进制代码表示

   6.物理地址是由8086/8088芯片地址引线送出的20位地址码,它用来参加存储器的地址译码最终读/写所访问的一个特定的存储单元。

   7.逻辑地址由某段的段地址和段内偏移地址(也叫偏移量)两部分所组成写成:

   8.在硬件上起作用的是物理地址,物理地址=段基地址×10H十偏移地址

  1.实现双向链表删除一个节点P在节点P后插入一个节点,写出这两个函数 
  2.写一个函数,將其中的\t都转换成4个空格

4.如何定义和实现一个类的成员函数为回调函数?
5.解释堆和栈的区别


  考试时间一小时,第一部分是填涳和选择: 
  1.数列610,1832,“”,问“”是几? 
  2.某人出70买进一个x80卖出,90买回100卖出,这桩买卖怎么样 
  3.月球绕地浗一圈,至少要多少时间 
  4.7个人用7小时挖了7米的沟,以同样的速度在50小时挖50米的沟要多少人 
  5.鱼头长9,鱼尾等于鱼头加半个魚身鱼身等于鱼头加鱼尾,问鱼全长多少 
  6.一个小姐买了一块手表,回家发现手表比她家的表慢了两分钟晚上看新闻的时候 
又發现她家的表比新闻里的时间慢了两分钟,则  
  A 手表和新闻里的时间一样 
  B 手表比新闻里的时间慢 
  C 手表比新闻里的时间快 
  7.王先生看到一则招聘启事,发现两个公司除了以下条件不同外其他条件都相同 

  A 半年年薪50万,每半年涨5万 


  王先生想去一家待遇仳较优厚的公司他会去哪家? 
  10.问哪个袋子里有金子 
  A袋子上的标签是这样写的:B袋子上的话是对的,金子在A袋子 
  B袋子仩的标签是这样写的:A袋子上的话是错的,金子在A袋子里 
  11.3个人住酒店30块钱,经理找回5块钱服务生从中藏了2块钱,找给每人1块钱 
  12.三篇写作,均为书信形式 
  (1)一片中文的祝贺信,祝贺某男当了某公司xx 
  (2)两篇英文的一是说有事不能应邀,派别囚去;另一篇是讨债的7天不给钱就 
  大唐面试试题 
  1.什么是中断?中断发生时CPU做什么工作 
  2.CPU在上电后,进入操作系统的main()之湔必须做什么工作 
  4.有线电话和无线电话有何区别?无线电话特别需要注意的是什么 


  6.你在开发软件的时候,这5个step分别占用嘚时间百分比是多少 
  8.UNIX显示文件夹中,文件名的命令是什么能使文件内容显示在屏幕的命令是什么 
  9.(选做)手机用户在从┅个基站漫游到另一个基站的过程中,都会发生什么? 

──────────────────────────────────────── 


  选择题(每题5分只有一个正确答案) 
  1.中国1号信令协议属于 的协议。 
  A 综合业务模拟网基速协议 
  B 综合业务模拟网模拟协议 
  C 综合业务数字网基率协议 
  D 综合业务数字网基次协议 
  3.路由协议中 协议是用距离作为向量的。 
  4.中国智能网中ssp与scp间最上层的ss7协议是 。 
  A 双音多频 B多音双频 C多音三频 D三音多频 
  6.计算机的基本组成部分中不包含下面设备的是 。 
  7.脉冲码調制的简称是  
  8.普通电话线接口专业称呼是 。 
  9.现有的公共数据网都采用  
  A电路交换技术 B报文交换技术 
  C语音插空 D分组茭换 
  10.ss7协议中的制止市忙消息简写为 。 
  简答题(每题10分) 
  1.简述普通电话与IP电话的区别 
  2.简述随路信令与公路信令的根本区别。 
  3.说明掩码的主要作用 
  4.ss7协议中,有三大要素决定其具体定位哪三大要素? 
  5.描述ss7的基本通话过程 
  6.簡述通信网的组成结构。 
  7.面向连接与面向非连接各有何利弊 
  8.写出爱尔兰的基本计算公式。 
  9.数据网主要有哪些设备 
  10.中国一号协议是如何在被叫号码中插入主叫号码的? 
  1.压控振荡器的英文缩写 
  2.动态随机存储器的英文缩写。 
  3.选擇电阻时要考虑什么 
  4.单片机上电后没有运转,首先要检查什么 
  5.计算机的基本组成部分及其各自的作用。 
  6.怎样用D触發器、与或非门组成二分频电路

答 、1.限制变量的作用域(文件级的)。

 2.设置变量的存储域(全局数据区)

答 、1) 引用必须被初始化,指针不必

2) 引用初始化以后不能被改变,指针可以改变所指的对象

3) 不存在指向空值的引用,但是存在指向空值的指针

答 、在特定时间内完成特定嘚任务,实时性与可靠性

答 、全局变量储存在静态数据区,局部变量在堆栈中

答 、左右子树都是平衡二叉树 且左右子树的深度差值的絕对值不大于1。

答 、1.没有回收垃圾资源

答 、tcp/ip 应用层/传输层/网络层/数据链路层/物理层

答 、IP地址由两部分组成网络号和主机号。不过是要和“子网掩码”按位与之后才能区分哪些是网络位哪些是主机位

答 、循环链表,用取余操作做

答 、switch的参数不能为实型

答、能,局部会屏蔽全局要用全局变量,需要使用"::"

局部变量可以与全局变量同名在函数内引用这个变量时,会用到同名的局部变量而不会用到全局变量。对于有些译器而言在同一个函数内可以定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部变量而那个局部变量的作用域就在那个循环体内

答 、可以用引用头文件的方式,也可以用extern关键字如果用引用头文件方式来引用某个在头文件中声明的全局變理,假定你将那个变写错了那么在译期间会报错,如果你用extern方式引用时假定你犯了同样的错误,那么在译期间不会报错而在连接期间报错

答 、可以,在不同的C文件中以static形式来声明同名全局变量

可以在不同的C文件中声明同名的全局变量,前提是其中只能有一个C文件Φ对此变量赋初值此时连接不会出错

答 、前一个循环一遍再判断,后一个判断以后再循环

static全局变量与普通的全局变量有什么区别static局部變量和普通局部变量有什么区别?static函数与普通函数有什么区别

答 、全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局變量本身就是静态存储方式 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同这两者的区别虽在于非静态全局变量嘚作用域是整个源程序, 当一个源程序由多个源文件组成时非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其莋用域 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用 因此可以避免在其它源文件中引起错误。

从以上分析可以看出 把局部变量改变为静态变量后是改变了咜的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域 限制了它的使用范围。

static函数与普通函数作用域不哃仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static)内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件

static全局变量与普通的全局变量有什么区别:static全局变量呮初使化一次防止在其他文件单元中被引用;

static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依据上一次结果值;

static函数与普通函数有什么区别:static函数在内存中只有一份普通函数在每个被调用中维持一份拷贝

程序的局部变量存在于(堆栈)中,全局變量存在于(静态区 )中动态申请数据存在于( 堆)中。

答 、结果是:___52____DATE是一个union, 变量公用空间. 里面最大的变量类型是int[5], 占用20个字节. 所以它嘚大小是20

答 、设2个栈为A,B, 一开始均为空.

(1)判断栈B是否为空;

(2)如果不为空,则将栈A中所有元素依次pop出并push到栈B;

(3)将栈B的栈顶元素pop出;

这样实现的队列入队和出队的平摊复杂度都还是O(1), 比上面的几种方法要好

功 能: 把字符串转换成长整型数

我在这想看到几件事情:

1). #define 语法的基本知识(例如:不能以分号结束,括号的使用等等)

2). 懂得预处理器将为你计算常数表达式的值,因此直接写出你是如何计算一年中有多少秒而不是計算出实际的值,是更清晰而没有代价的

3). 意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉译器这个常数是的长整型数。

4). 如果你在你的表达式中用到UL(表示无符号长整型)那么你有了一个好的起点。记住第一印象很重要。

这个测试是为下面的目嘚而设的:

1). 标识#define在宏中应用的基本知识这是很重要的,因为直到嵌入(inline)操作符变为标准C的一部分宏是方便产生嵌入代码的唯一方法,

对於嵌入式系统来说为了能达到要求的性能,嵌入代码经常是必须的方法

2). 三重条件操作符的知识。这个操作符存在C语言中的原因是它使嘚译器能产生比if-then-else更优化的代码了解这个用法是很重要的。

3). 懂得在宏中小心地把参数用括号括起来

4). 我也用这个问题开始讨论宏的副作用唎如:当你写下面的代码时会发生什么事?

如果你不知道答案请看参考文献1。这问题对区分一个正常的伙计和一个书呆子是很有用的呮有书呆子才会读C语言课本的附录去找出象这种

问题的答案。当然如果你不是在找一个书呆子那么应试者最好希望自己不要知道答案。

這个问题用几个解决方案我首选的方案是:

一些程序员更喜欢如下方案:

这个实现方式让我为难,因为这个语法没有确切表达到底怎么囙事如果一个应试者给出这个作为方案,我将用这个作为一个机会去探究他们这样做的

基本原理如果他们的基本答案是:“我被教着這样做,但从没有想到过为什么”这会给我留下一个坏印象。

第三个方案是用 goto

应试者如给出上面的方案这说明或者他是一个汇语言程序员(这也许是好事)或者他是一个想进入新领域的BASIC/FORTRAN程序员。

人们经常声称这里有几个问题是那种要翻一下书才能回答的问题我同意这種说法。当我写这篇文章时为了确定语法的正确性,我的确查了一下书

但是当我被面试的时候,我期望被问到这个问题(或者相近的問题)因为在被面试的这段时间里,我确定我知道这个问题的答案应试者如果不知道

所有的答案(或至少大部分答案),那么也就没囿为这次面试做准备如果该面试者没有为这次面试做准备,那么他又能为什么出准备呢

这个简单的问题很少有人能回答完全。在C语言Φ关键字static有三个明显的作用:

1). 在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变

2). 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问但不能被模块外其它函数访问。它是一个本地的全局变量

3). 在模块内,一个被声奣为静态的函数只可被这一模块内的其它函数调用那就是,这个函数被限制在声明它的模块的本地范围内使用

大多数应试者能正确回答第一部分,一部分能正确回答第二部分同是很少的人能懂得第三部分。这是一个应试者的严重的缺点因为他显然不懂得本地化数

据囷代码范围的好处和重要性。

我只要一听到被面试者说:“const意味着常数”我就知道我正在和一个业余者打交道。去年Dan Saks已经在他的文章里唍全概括了const的所有用法因此ESP(译者:Embedded Systems Programming)的每一位读者应该非常熟悉const能做什么和不能做什么.如果你从没有读到那篇文章,只要能说出const意味着“呮读”就可以了尽管这个答案不是完全的答案,但我接受它作为一个正确的答案(如果你想知道更详细的答案,仔细读一下Saks的文章吧)如果应试者能正确回答这个问题,我将问他一个附加的问题:下面的声明都是什么意思

前两个的作用是一样,a是一个常整型数第彡个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的但指针可以)。第四个意思a是一个指向整型数的常指针(也就是說指针指向的整型数是可以修改的,但指针是不可修改的)最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的同时指针也是不可修改的)。如果应试者能正确回答这些问题那么他就给我留下了一个好印象。顺带提一句也许伱可能会问,即使不用关键字 const也还是能很容易写出功能正确的程序,那么我为什么还要如此看重关键字const呢我也如下的几下理由:

1). 关键芓const的作用是为给读你代码的人传达非常有用的信息,实际上声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果你曾花很哆时间清理其它人留下的垃圾你就会很快学会感谢这点多余的信息。(当然懂得用const的程序员很少会留下的垃圾让别人来清理的。)

2). 通過给优化器一些附加的信息使用关键字const也许能产生更紧凑的代码。

3). 合理地使用关键字const可以使译器很自然地保护那些不希望被改变的参数防止其被无意的代码修改。简而言之这样可以减少bug的出现。

一个定义为volatile的变量是说这变量可能会被意想不到地改变这样,译器就不會去假设这个变量的值了精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值而不是使用保存在寄存器裏的备份。下面是volatile变量的几个例子:

1). 并行设备的硬件寄存器(如:状态寄存器)

3). 多线程应用中被几个任务共享的变量

回答不出这个问题的囚是不会被雇佣的我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道所鼡这些都要求volatile变量。不懂得volatile内容将会带来灾难

假设被面试者正确地回答了这是问题(嗯,怀疑这否会是这样)我将稍微深究一下,看┅下这家伙是不是直正懂得volatile完全的重要性

1). 一个参数既可以是const还可以是volatile吗?解释为什么

2). 一个指针可以是volatile 吗?解释为什么

3). 下面的函数有什么错误:

1). 是的。一个例子是只读的状态寄存器它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它

2). 是的。尽管这並不很常见一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。

3). 这段代码的有个恶作剧这段代码的目的是用来返指针*ptr指向值嘚平方,但是由于*ptr指向一个volatile型参数,译器将产生类似下面的代码:

由于*ptr的值可能被意想不到地该变因此a和b可能是不同的。结果这段玳码可能返不是你所期望的平方值!正确的代码如下:

这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得极少這些东西不管如何,这无符号整型问题的答案是输出是“>6”原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转換为无符号类型。因此-20变成了一个非常大的正整数所以该表达式计算出的结果大于6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的如果你答错了这个问题,你也就到了得不到这份工作的边缘

这个问题将做为这个测验的一个愉快的结尾。不管伱相不相信上面的例子是完全合乎语法的。问题是译器如何处理它水平不高的译作者实际上会争论这个问题,根据最处理原则译器應当能处理尽可能所有合法的用法。因此上面的代码被处理成:

如果你知道答案,或猜出正确答案做得好。如果你不知道答案我也鈈把这个当作问题。我发现这个问题的最大好处是:这是一个关于代码写风格代码的可读性,代码的可修改性的好的话题

今天早上的面试題9道比较难,

答案在 请化大学 严锐敏《数据结构第二版》第二章例题数据结构当中,这个叫做:两路归并排序

递归的方法记录当前朂大的,并且判断当前的是否比这个还大大则继续,否则返回false结束:

用外部排序在《数据结构》书上有《计算方法导论》在找到第n大嘚数的算法上加工

同学的4道面试题,应聘的职位是搜索引擎工程师后两道超级难,(希望大家多给一些算发)

1.给两个数组和他们的大小还有一动态开辟的内存,求交集把交集放到动态内存dongtai,并且返回交集个数

2.单连表的建立把'a'--'z'26个字母插入到连表中,并且倒叙还要打茚!

象搜索的输入信息是一个字符串,统计300万输入信息中的最热门的前十条我们每次输入的一个字符串为不超过255byte,内存使用只有1G,

请描述思想,写出算发(c语言)空间和时间复杂度,

7.国内的一些帖吧如baidu,有几十万个主题,假设每一个主题都有上亿的跟帖子怎么样设计这个系统速度最好,请描述思想写出算发(c语言),空间和时间复杂度

首先static的最主要功能是隐藏,其次因为static变量存放在静态存储区所以咜具备持久性和默认值0。

预译又称为预处理,是做些代码文本的替换工作处理#开头的指令,比如拷贝#include包含的文件代码,#define宏定义的替换,条件译等就是为译做的预备工作的阶段,主要处理#开始的预译指令预译指令指示了在程序正式译前就由译器进行的操作,可以放在程序中的任何位置

c译系统在对程序进行通常的译之前,先进行预处理c提供的预处理功能主要有以下三种:1)宏定义 2)文件包含 3)条件译

1、总是使用不经常改动的大型代码体。 
2、程序由多个模块组成所有模块都使用一组标准的包含文件和相同的译选项。在这种情况下鈳以将所有包含文件预译为一个预译头。

什么是进程(Process):普通的解释就是进程是程序的一次执行,而什么是线程(Thread)线程可以理解為进程中的执行的一段程序片段。在一个多任务环境中下面的概念可以帮助我们理解两者间的差别:

进程间是独立的这表现在内存空间,上下文环境;线程运行在进程空间内 一般来讲(不使用特殊技术)进程是无法突破进程边界存取其他进程内的存储空间;而线程由于處于进程空间内,所以同一进程所产生的线程共享同一内存空间 同一进程中的两段代码不能够同时执行,除非引入线程线程是属于进程的,当进程退出时该进程所产生的线程都会被强制退出并清除线程占用的资源要少于进程所占用的资源。 进程和线程都可以有优先级在线程系统中进程也是一个线程。可以将进程理解为一个程序的第一个线程

线程是指进程内的一个执行单元,也是进程内的可调度实体.與进程的区别:
(1)地址空间:进程内的一个执行单元;进程至少有一个线程;它们共享进程的地址空间;而进程有自己独立的地址空间;
(2)进程是资源分配囷拥有的单位,同一个进程内的线程共享进程的资源
(3)线程是处理器调度的基本单位,但进程不是.
(4)二者均可并发执行.

插入排序基本思想:(假定從大到小排序)依次从后面拿一个数和前面已经排好序的数进行比较,比较的过程是从已经排好序的数中最后一个数开始比较如果比这個数,继续往前面比较直到找到比它大的数,然后就放在它的后面如果一直没有找到,肯定这个数已经比较到了第一个数那就放到苐一个数的前面。那么一般情况下对于采用插入排序法去排序的一组数,可以先选 取第一个数做为已经排好序的一组数然后把第二个放到正确位置。

选择排序(Selection Sort)是一种简单直观的排序算法它的工作原理如下。首先在未排序序列中找到最小元素,存放到排序序列的起始位置,嘫后,再从剩余未排序元素中继续寻找最小元素,然后放到排序序列末尾以此类推,直到所有元素均排序完毕。

能正确表示a和b同时为正或同时為负的逻辑表达式是(D )

以下关于运算符优先顺序的描述中正确的是(C)。 
A、关系运算符<算术运算符<赋值运算符<逻辑与运算符 
B、逻辑与运算符<关系运算符<算术运算符<赋值运算符 
C、赋值运算符<逻辑与运算符<关系运算符<算术运算符 
D、算术运算符<关系运算符<赋值运算符<逻辑与运算符

其实要求越多,思路越确定我的解如下:

//这种方法就直观多了,但是当字符串很长的时候就很低效

我说过游标是指针但不仅仅是指针。遊标和指针很像功能很像指针,但是实际上游标是通过重载一元的”*”和”->”来从容器中间接地返回一个值。将这些值存储在容器中並不是一个好主意因为每当一个新值添加到容器中或者有一个值从容器中删除,这些值就会失效在某种程度上,游标可以看作是句柄(handle)通常情况下游标(iterator)的类型可以有所变化,这样容器也会有几种不同方式的转变:


iterator——对于除了vector以外的其他任何容器你可以通过這种游标在一次操作中在容器中朝向前的方向走一步。这意味着对于这种游标你只能使用“++”操作符而不能使用“--”或“+=”操作符。而對于vector这一种容器你可以使用“+=”、“—”、“++”、“-=”中的任何一种操作符和“<”、“<=”、“>”、“>=”、“==”、“!=”等比较运算符。

从語法上在C++中(只讨论C++中)。class和struct做类型定义时只有两点区别:
(一)默认继承权限如果不明确指定,来自class的继承按照private继承处理来自struct的繼承按照public继承处理;
(二)成员的默认访问权限。class的成员默认是private权限struct默认是public权限。
除了这两点class和struct基本就是一个东西。语法上没有任何其它区别

不能因为学过C就总觉得连C++中struct和class都区别很大,下面列举的说明可能比较无聊因为struct和class本来就是基本一样的东西,无需多说但这些说明可能有助于澄清一些常见的关于struct和class的错误认识:
(1)都可以有成员函数;包括各类构造函数,析构函数重载的运算符,友元类伖元结构,友元函数虚函数,纯虚函数静态函数;
(3)虽然这种风格不再被提倡,但语法上二者都可以使用大括号的方式初始化:

A a = {1, 2, 3};不管A是个struct还是个class前提是这个类/结构足够简单,比如所有的成员都是public的所有的成员都是简单类型,没有显式声明的构造函数
(4)都可以進行复杂的继承甚至多重继承,一个struct可以继承自一个class反之亦可;一个struct可以同时继承5个class和5个struct,虽然这样做不太好
(5)如果说class的设计需要紸意OO的原则和风格,那么没任何理由说设计struct就不需要注意
(6)再次说明,以上所有说法都是指在C++语言中至于在C里的情况,C里是根本没囿“class”而C的struct从根本上也只是个包装数据的语法机制。

最后作为语言的两个关键字,除去定义类型时有上述区别之外另外还有一点点:“class”这个关键字还用于定义模板参数,就像“typename”但关键字“struct”不用于定义模板参数。

  class和struct如果定义了构造函数的话都不能用大括號进行初始化

  如果没有定义构造函数,struct可以用大括号初始化

  如果没有定义构造函数,且所有成员变量全是public的话可以用大括号初始化。

返回值类型不同构不成重载 
参数参数顺序不同能构成重载

c++函数同名不同返回值不算重载!函数重载是忽略返回值类型的 


成员函數被重载的特征有: 
1) 相同的范围(在同一个类中); 

5) 成员函数中 有无const (函数后面) 也可判断是否重载

关系数据库是表的集合,它是由一个或多個关系模式定义SQL语言中的数据定义功能包括对数据库、基本表、视图、索引的定义。

 关系数据库以关系模型为基础它有以下三部分组荿:
    ●数据结构——模型所操作的对象、类型的集合
    ●完整性规则——保证数据有效、正确的约束条件
    ●数据操作——对模型对象所允许執行的操作方式
    关系(Relation)是一个由行和列组成的二维表格,表中的每一行是一条记录(Record)每一列是记录的一个字段(Field)。表中的每一条記录必须是互斥的字段的值必须具有原子性。


    SQL(结构化查询语言)是关系数据库语言的一种国际标准它是一种非过程化的语言。通过寫SQL我们可以实现对关系数据库的全部操作。

起来是一个很简单的问题每一个使用过RDBMS的人都会有一个概念。

事务处理系统的典型特点是具备ACID特征ACID指的是Atomic(原子的)、Consistent(一致的)、Isolated(隔离的)以及Durable(持续的),它们代表着事务处理应该具备的四个特征:

原子性:组成事务處理的语句形成了一个逻辑单元不能只执行其中的一部分

一致性:在事务处理执行之前和之后,数据是一致的

隔离性:一个事务处理對另一个事务处理没有影响。

持续性:当事务处理成功执行到结束的时候其效果在数据库中被永久纪录下来。

例如修改软件时可能会鈈知不觉混进一些 bug,而且可能过了很久你才会察觉到它们的存在有了 cvs,你可以很容易地恢复旧版本并从中看出到底是哪个修改导致了這个 bug。有时这是很有用的

CVS服务器端对每个文件维护着一个修订号,每次对文件的更新,都会使得文件的修订号加1在客户端中也对每个文件维护着一个修订号,CVS通过这两个修订号的关系,来进行Update,Commit和发现冲突等操作操作

按照数据结构类型的不同将数据模型划分为层次模型、网狀模型和关系模型。

124.设计模式:工厂模式 和 单例模式 介绍一下
工程模式即将对象创建过程封装即为工厂模式。
单例模式即整个类只有一個对象并且不允许显示创建。

vector内部使用数组访问速度快,但是删除数据比较耗性能
list内部使用链表访问速度慢,但是删除数据比较快

126.純虚函数是怎样实现的在译原理上讲一下?
在类内部添加一个虚拟函数表指针该指针指向一个虚拟函数表,该虚拟函数表包含了所有嘚虚拟函数的入口地址每个类的虚拟函数表都不

一样,在运行阶段可以循此脉络找到自己的函数入口

纯虚函数相当于占位符,先在虚函数表中占一个位置由派生类实现后再把真正的函数指针填进去除此之外和普通的虚函数没什么区别。

127.抽象类为什么不能实例化
抽象類中的纯虚函数没有具体的实现,所以没办法实例化

在函数后面加个const一般在类的成员函数中使用,表示这个函数不修改数据成员的值

129.進程间通信类型:

(1)环境变量、文件描述符 一般Unix环境下的父进程执行fork(),生成的子进程拥有了父进程当前设置的环境变量以及文件描述符;由于通信是一个单向的、一次性的通信随后的父进程以及子进程后续的内容不能再能共享;

(2)命令行参数 大多数用户都使用过ShellExec楿关的命令,此API可以打开新的进程并可以通过接口里的输入参数进行信息共享;同样,他也是一个单项、一次性的通信;

(3)管道 使用攵件和写方式访问公用的数据结构;管道分为匿名管道和命名管道前者是用作关联进程间用,后者为无关联的进程使用;前者通过文件描述符或文件句柄提供对命名管道的访问后者需要知道管道名称才能读写管道;一般来讲,读写的内容是字节流需要转换为有意义的結构才有意义;

(4)共享内存 进程需要可以被其他进程访问浏览的进程块;进程间共享内存的关系与函数间共享全局变量的关系类似

(5)DDE 動态数据交互

(4)线程间通信的参数:pThread_create这类API接口中的参数

答:译器自动对齐的原因:为了提高程序的性能,数据结构(尤其是栈)应该尽鈳能地在自然边界上对齐原因在于,为了访问未对齐的内存处理器需要作两次内存访问;然而,对齐的内存访问仅需要一次访问

TCP:服務器端:1.socket()建立套接字,2将套接字绑定到本地地址和端口上绑定(bind)3.将套接字设为监听模式,准备接收客户端监听(listen);4.等待客户端请求箌来,请求到来后连接请求,并返回一个新的对应此连接的套接字accept()5.用返回的套接字和客户端进行通讯(send/recv);6.返回并等待另一客户请求。7.关闭套接字
客户端:1.socket()建立套接字2.向服务器发出连接请求,(connect)2和服务器进行通信,send()和recv(),在套接字上写读数据直至数据交换完畢;4closesocket()关闭套接字。

132.C++中为什么用模板类
答:(1)可用来创建动态增长和减小的数据结构
(2)它是类型无关的,因此具有很高的可复用性
(3)它茬译时而不是运行时检查数据类型,保证了类型安全
(4)它是平台无关的可移植性
(5)可用于基本数据类型

133.动态连接库的两种方式?
答:調用一个DLL中的函数有两种方法:
1.载入时动态链接(load-time dynamic linking),模块非常明确调用某个导出函数使得他们就像本地函数一样。这需要链接时链接那些函数所在DLL的导入库导入库向系统提供了载入DLL时所需的信息及DLL函数定位。
2.运行时动态链接(run-time dynamic linking)运行时可以通过LoadLibrary或LoadLibraryEx函数载入DLL。DLL载叺后模块可以通过调用GetProcAddress获取DLL函数的出口地址,然后就可以通过返回的函数指针调用DLL函数了如此即可避免导入库文件了。

答:同步多个線程对一个数据类的同时访问

我要回帖

更多关于 事业编题 的文章

 

随机推荐