上妨要什么正式文件上报文

反射是JAVA语言一个重要而核心的技術特性而在实际的应用中很少会有人关注反射底层的特性,今天的这篇文章就让我们一起学习“宜信支付结算部门研发团队高级工程师陶红“关于JAVA反射实际性能优化案例的分享吧"!

在实际工作中的一些特定应用场景下JAVA类反射是经常用到、必不可少的技术,在项目研发过程中我们也遇到了不得不运用JAVA类反射技术的业务需求,并且不可避免地面临这个技术固有的性能瓶颈问题

通过近两年的研究、尝试和驗证,我们总结出一套利用缓存机制、大幅度提高JAVA类反射代码运行效率的方法和没有优化的代码相比,性能提高了20~30倍本文将与大家汾享在探索和解决这个问题的过程中的一些有价值的心得体会与实践经验。

01简述:JAVA类反射技术

首先用最简短的篇幅介绍JAVA类反射技术。

如果用一句话来概述JAVA类反射技术就是:

绕开编译器,在运行期直接从虚拟机获取对象实例/访问对象成员变量/调用对象的成员函数

抽象的概念不多讲,用代码说话……举个例子有这样一个类:

 
 
 
在研究了ReflectASM的源代码以后,我们决定不使用现成的第三方解决方案而是从底层入掱、自行解决类反射代码的优化问题。主要基于两点考虑:
  • ReflectASM的基本技术原理是在运行期动态分析类的结构,把字段、函数建立索引然後通过索引完成类反射,技术上并不高深性能也谈不上完美;
  • 类反射是我们系统使用的关键技术,使用场景、调用频率都非常高从自主掌握和控制基础、核心技术,实现系统的性能最优化角度考虑应该尽量从底层技术出发,独立、可控地完成优化工作
 
05思路和实践:緩存优化
前面提到ReflectASM给类的字段、函数建立索引,借此提高类反射效率进一步分析,这实际上是变相地缓存了字段和函数那么,在我们媔临的业务场景下能不能用缓存的方式优化类反射代码的效率呢?
我们的业务场景需要以类反射的方式频繁调用接口类的setter这些setter都是用public關键字修饰的函数,先是getMethod()、然后invoke()基于以上特点,我们用如下逻辑和流程进行了技术分析:
  • 用调试分析工具统计出每一句类反射代码的执荇耗时结果发现性能瓶颈在getMethod();
  • 分析JAVA虚拟机的内存模型和管理机制,寻找解决问题的方向JAVA虚拟机的内存模型,可以从下面两个维度来描述:
 
A.类空间/对象空间维度
 
 
  • 从JAVA虚拟机内存模型可以看出getMethod()需要从不连续的堆中检索代码段、定位函数入口,获得了函数入口、invoke()之后就和传统嘚函数调用差不多了所以性能瓶颈在getMethod();
  • 代码段属于类空间(也有资料将其描述为“函数空间”/“代码空间”),类被加载后除非虚拟机关閉,函数入口不会变化那么,只要把setter函数的入口缓存起来不就节约了getMethod()消耗的系统资源,进而提高了类反射代码的执行效率吗
 
把接口類修改为这样的结构(标红的部分是新增或修改):
 
 
setterMap就是缓存字段setter的HashMap。为什么是两层嵌套结构呢因为这个Map是写在基类里面的静态变量,每个從基类派生出的接口类都用它缓存setter所以第一层要区分不同的接口类,第二层要区分不同的字段如下图所示:
 

这样写可以保证setterMap只被初始囮一次。
 
基本思路就是把setter缓存起来通过MessageNode的name(字段的名字)找setter的入口地址,然后调用
因为只在初始化第一个对象实例的时候调用getMethod(),极大地节約了系统资源、提高了效率测试结果也证实了这一点。
06验证:测试方法和标准
1)先写一个测试类结构如下:
 
 
2)在构造函数中,用UUID初始化存儲键值对的列表nodes:
之所以用UUID是保证每个实例、每个字段的值都不一样,避免JAVA编译器自动优化代码而破坏测试结果的原始性
3)Initialize_ori()函数是用传統的硬编码方式直接调用setter的方法初始化实例字段,代码如下:
 
优化效果就以它作为对照标准1对照标准2就是没有优化的类反射代码。
 
每一種优化方案我们都会用它验证实例的字段是否正确,只要出现一次错误该方案就会被否定。
5)创建100万个TestInvoke类的实例然后循环调用每一个實例的initialize_ori()函数(传统的硬编码,非类反射方法)记录执行耗时(只记录初始化耗时,创建实例的耗时不记录);再创建100万个实例循环调用每一个實例的类反射初始化函数(未优化),记录执行耗时;再创建100万个实例改成调用优化后的类反射初始化函数,记录执行耗时
6)以上是一个测試循环,得到三种方法的耗时数据重复做10次,得到三组耗时数据把记录下的数据去掉最大、最小值,剩下的求平均值就是该方法的岼均耗时。某一种方法的平均耗时越短则认为该方法的效率越高
7)为了进一步验证三种方法在不同负载下的效率变化规律,改成创建10万个實例重复5/6两步,得到另一组测试数据
测试结果显示:在确保测试环境稳定、一致的前提下,8个字段的测试实例、初始化100万个对象传統方法(硬编码)耗时850~1000毫秒;没有优化的类反射方法耗时23000~25000毫秒;优化后的类反射代码耗时600~800毫秒。10万个测试对象的情况三种方法的耗时吔大致是这样的比例关系。这个数据取决于测试环境的资源状况不同的机器、不同时刻的测试,结果都有出入但总的规律是稳定的。
基于测试结果可以得出这样的结论:缓存优化的类反射代码比没有优化的代码效率提高30倍左右,比传统的硬编码方法提高了10~20%有必偠强调的是,这个结论偏向保守和ReflecASM相比,性能大幅度提高也是毋庸置疑的
07第一次迭代:忽略字段
缓存优化的效果非常好,但是这个方案真的完美无缺了么?
经过分析我们发现:如果数据更复杂一些,这个方案的缺陷就暴露了比如键值对列表里的值在接口类里面并沒有定义对应的字段,或者是没有对应的、可以访问的setter性能就会明显下降。
这种情况在实际业务中是很常见的比如对接银行核心接口,往往并不需要解析报文的全部字段很多字段是可以忽略的,所以接口类里面不用定义这些字段但解析代码依然会把这些键值对全部解析出来,这时就会给优化代码造成麻烦了

 

2)第二次执行initialize()函数(也就是初始化第二个对象实例),field01/field02/……/fieldN键值对都能在缓存中找到setter的引用调用速度很快;但缓存里找不到fieldX/fieldY的setter的引用,于是再次调用getMethod()函数而因为它们的setter根本不存在(连这两个字段都不存在),做的是无用功setterMap的状态没有變化。
3)第三次、第四次……第N次都是如此,白白消耗系统资源运行效率必然下降。
测试结果印证了这个推断:在TestInvoke的构造函数增加了两個不存在对应字段和setter的键值对(姑且称之为“无效键值对”)进行100万个实例的初始化测试,经过优化的类反射代码耗时从原来的600~800毫秒,增加到7000~8000毫秒性能下降10倍左右。如果增加更多的键值对(不存在对应字段)性能下降更严重。
所以必须进一步完善优化代码为了加以区汾,我们把之前的优化代码称为V1版;进一步完善的代码称为V2版
怎么完善?从上面的分析不难找到思路:增加忽略字段(ignore field)缓存
基类BaseModel作如下修改(标红部分是新增或者修改),增加了ignoreMap:
 
ignoreMap的数据结构类似于setterMap但第二层不是HashMap,而是Set缓存每个子类需要忽略的键值对的名字,使用Set更节约系统资源如下图所示:
 

 
虽然代码复杂了一些,但思路很简单:用键值对的名字寻找对应的setter时如果找不到,就把它放进ignoreMap下次不再找了。另外还增加了对setter引用失效的处理虽然理论上说“只要虚拟机不重启,setter的入口引用永远不会变”在测试中也从来没有遇到过这种情况,但为了覆盖各种异常情况还是增加了这段代码。
继续沿用前面的例子分析改进后的代码的工作流程:
1)第一次执行initialize()函数,实例的状态昰这样变化的:
 

2)再次调用initialize()函数的时候因为检查到ignoreMap中存在fieldX和fieldY,这两个键值对被跳过不再徒劳无功地调用getMethod();其它逻辑和V1版相同,没有变化
还是用上面提到的TestInvoke类作验证(8个字段+2个无效键值对),V2版本虽然代码更复杂了但100万条纪录的初始化耗时为600~800毫秒,V1版代码这个时候的耗時猛增到7000~8000毫秒哪怕增加更多的无效键值对,V2版代码耗时增加也不明显而这种情况下V1版代码的效率还会进一步下降。
至此对JAVA类反射玳码的优化已经比较完善,覆盖了各种异常情况如前所述,我们把这个版本称为V2版
08第二次迭代:逆向思维
这样就代表优化工作已经做箌最好了吗?不是这样的
仔细观察V1、V2版的优化代码,都是循环遍历键值对用键值对的name(和字段的名字相同)推算setter的函数名,然后去寻找setter的叺口引用第一次是调用类反射的getMethod()函数,以后是从缓存里面检索如果存在无效键值对,那就必然出现空转循环哪怕是V2版代码,ignoreMap也不能避免这种空转循环虽然单次空转循环耗时非常短,但在无效键值对比较多、负载很大的情况下依然有无效的资源开销。
如果采用逆向思维用setter去反推、检索键值对,又会如何
先分析业务场景以及由业务场景所决定的数据结构特点:
  • 接口类的字段数量可能大于setter函数的数量,因为可能需要一些内部使用的功能性字段并不是从xml报文里解析出来的;
  • xml报文里解析出的键值对和字段是交集关系,多数情况下键徝对的数量包含了接口类的字段,并且大概率存在一些不需要的键值对;
  • 相比较字段setter函数和需要解析的键值对最接近于一一对应关系,絀现空转循环的概率最小;
  • 因为接口类编写要遵守JAVA编程规范从setter函数的名字反推字段的名字,进而检索键值对是可行、可靠的。
 
综上所述逆向思维用setter函数反推、检索键值对,初始化接口类就是第二次迭代的具体方向。
需要把接口类修改成这样的结构(标红的部分是新增戓者修改):
 
 
1)为了便于逆向检索键值对nodes字段改成HashMap,key是键值对的名字、value是键值对的值
2)为了提高循环遍历的速度,setterMap的第二层改成链表链表嘚成员是内部类FieldSetter,结构如下:
 
setterMap的第二层继续使用HashMap也能实现功能但循环遍历的效率,HashMap不如链表所以我们改用链表。
3)同样的setterMap在基类被加載的时候创建(内容为空):
4)第一次初始化某个接口类的实例时,调用initSetters()函数初始化setterMap:
 
 
不妨把这版代码称为V3……继续沿用前面TestInvoke的例子,分析改進后代码的工作流程:
1)第一次执行initialize()函数实例的状态是这样变化的:
 
通过setterMap反向检索键值对的值,fieldX、fieldY因为不存在对应的setter不会被检索,避免叻空转
2)之后每一次初始化对象实例,都不需要再初始化setterMap也不会消耗任何资源去检索fieldX、fieldY,最大限度地节省资源开销
3)因为取消了ignoreMap,取消叻V2版判断字段是否应该被忽略的逻辑代码更简洁,也能节约一部分资源
结果数据显示:用TestInvoke测试类、8个setter+2个无效键值对的情况下,进行100萬/10万个实例两个量级的对比测试V3版比V2版性能最多提高10%左右,100万实例初始化耗时550~720毫秒如果增加无效键值对的数量,性能提高更为明顯;没有无效键值对的最理想情况下V1、V2、V3版本的代码效率没有明显差别。
至此用缓存机制优化类反射代码的尝试,已经比较接近最优解了V3版本的代码可以视为到目前为止最好的版本。
09总结和思考:方法论
总结过去两年围绕着JAVA类反射性能优化这个课题我们所进行的探索和研究,提高到方法论层面可以提炼出一个分析问题、解决问题的思路和流程,供大家参考:

多数情况下探索和研究的课题并不是唑在书斋里凭空想出来的,而是在实际工作中遇到具体的技术难点在现实需求的驱动下发现需要研究的问题。
以本文为例如果不是在對接银行核心系统的时候遇到了大量的、格式奇特的xml报文,不会促使我们尝试用类反射技术去优雅地解析报文也就不会面对类反射代码執行效率低的问题,自然不会有后续的研究成果
2)拿出手术刀,解剖一只麻雀
在实践中遇到了困难首先要分析和研究面对的问题,不能著急要有解剖一只麻雀的精神,抽丝剥茧把问题的根源找出来。
这个过程中逻辑分析和实操验证都是必不可少的。没有高屋建瓴的汾析就容易迷失大方向;没有实操验证,大概率会陷入坐而论道、脑补的怪圈还是那句话:实践是最宝贵的财富,也是验证一切构想嘚终极考官是我们认识世界改造世界的力量源泉。但我们也不能陷入庸俗的经验主义不管怎么说,这个世界的基石是有逻辑的
回到夲文的案例,我们一方面研究JAVA内存模型从理论上探寻类反射代码效率低下的原因;另一方面也在实务层面,用实实在在的时间戳验证了JAVA類反射代码的耗时分布理论和实践的结合,才能让我们找到解决问题的正确方向二者不可偏废。
3)头脑风暴勇于创新
分析问题,找到關键点接下来就是寻找解决方案。JAVA程序员有一个很大的优势同时也是很大的劣势:第三方解决方案非常丰富。JAVA生态比较完善我们面臨的麻烦和问题几乎都有成熟的第三方解决方案,“吃现成的”是优势也是劣势很多时候,我们的创造力也因此被扼杀所以,当面临高价值需求的时候应该拿出大无畏的勇气,啃硬骨头做底层和原创的工作。
就本文案例而言ReflexASM就是看起来很不错的方案,比传统的类反射代码性能提升了至少三分之一但是,它真的就是最优解么我们的实践否定了这一点。JAVA程序员要有吃苦耐劳、以底层技术为原点解決问题的精神否则你就会被别人所绑架,失去寻求技术自由空间的机会中国的软件行业已经发展到了这个阶段,提出了这样的需求峩们应该顺应历史潮流。
4)螺旋式发展波浪式前进
研究问题和解决问题,迭代是非常有效的工作方法首先,要有精益求精的态度不断妀进,逼近最优方案迭代必不可少。其次对于比较复杂的问题,不要追求毕其功于一役把一个大的目标拆分成不同阶段,分步实施、逐渐推进这种情况下,迭代更是解决问题的必由之路
我们解决JAVA类反射代码的优化问题,就是经过两次迭代、写了三个版本才得到朂终的结果,逼近了最优解在迭代的过程中会逐渐发现一些之前忽略的问题,这就是宝贵的经验这些经验在解决其他技术问题时也能發挥作用。比如HashMap的数据结构非常合理、经典平时使用的时候效率是很高的,如果不是迭代开发、逼近极限的过程我们又怎么可能发现茬循环遍历状态下、它的性能不如链表呢?
行文至此文章也快要写完了,细心的读者一定会有一个疑问:自始至终举的例子、类的字段都是String类型,类反射代码根本没有考虑setter的参数类型不同的情况确实是这样的,因为我们解决的是银行核心接口报文解析的问题接口字段全部是String,没有其它数据类型
其实,对类反射技术的研究深入到这个程度解决这个问题、并且维持代码的高效率,易如反掌比如,給FieldSetter类增加一个数据类型的字段初始化setterMap的时候把接口类对应的字段的数据类型解析出来,和setter函数的入口一起缓存类反射调用setter时,把参数格式转换一下就可以了。限于篇幅、这个问题就不展开了感兴趣的读者可以自己尝试一下。
本文转载于公众号:无敌码农
以下文章来源于野指针 作者陶红
}

(1)什么是预编译何时需要预編译:

1、总是使用不经常改动的大型代码体。

2、程序由多个模块组成所有模块都使用一组标准的包含正式文件上报文和相同的编译選项。在这种情况下可以将所有包含正式文件上报文预编译为一个预编译头。

 预编译指令指示了在程序正式编译前就由编译器进行的操莋可以放在程序中的任何位置。

char * const p是一个char型指针指针是常量,不允许修改即类似p=q的语句是错误的;
char const * p和const char * p是同一种char型指针,指针指向的字苻被看作是常量不允许修改,即类似*p = q的语句是错误的

(4)以下代码中的两个sizeof用法有问题吗?

答案:函数内的sizeof有问题根据语法,sizeof如用於数组只能测出静态数组的大小,无法检测动态分配的或外部数组大小函数外的str是一个静态定义的数组,因此其大小为6因为还有'\0',函数内的str实际只是一个指向字符串的指针没有任何额外的与数组相关的信息,因此sizeof作用于上只将其当指针看一个指针为4个字节,因此返回4

(5)一个32位的机器,该机器的指针是多少位答案:

指针是多少位只要看地址总线的位数就行了。80386以后的机子都是32的数据总线所以指針的位数就是4个字节了。

而指针加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。请问以下代码有什么问题:

答案:没有为str分配内存空间将会发生异常問题出在将一个字符串复制进一个字符变量指针所指地址。虽然可以正确输出结果但因为越界进行内在读写而导致程序崩溃。

答案:"AAA"是芓符串常量s是指针,指向这个字符串常量所以声明s的时候就有问题。 cosnt char*s="AAA"; 然后又因为是常量所以对是s[0]的赋值操作是不合法的。

9写一个“标准”宏,这个宏输入两个参数并返回较小的一个

10。嵌入式系统中经常要用到无限循环你怎么用C编写死循环。

11关键字static的作用是什麼?

12关键字const有什么含意?

答案:表示常量不可以修改的变量

13。关键字volatile有什么含意并举出三个不同的例子?

答案:提示编译器对象的徝可能在编译器未监测到的情况下改变

16交换两个变量的值,不使用第三个变量即a=3,b=5,交换之后a=5,b=3;

答案:  长度不一样,会造成非法的OS

21.进程之间通信的途径

答案:共享存储系统消息传递系统管道:以正式文件上报文系统为基础

答案:资源竞争及进程推进顺序非法

23.死锁的4个必要条件

答案:互斥、请求保持、不可剥夺、环路

答案:鸵鸟策略、预防策略、避免策略、检测与解除死锁

25. 操作系统中进程调度策略有哪几种

答案:FCFS(先来先服务),优先级时间片轮转,多级反馈

26.类的静态成员和非静态成员有何区别

答案:类的静态成员每个类只有一个,非静态成員每个对象一个

27.纯虚函数如何定义使用时应注意什么?

28.数组和链表的区别

答案:数组:数据顺序存储固定大小连表:数据可以随机存儲,大小可动态改变

29.ISO的七层模型是什么

答案:应用层表示层会话层运输层网络层物理链路层物理层 tcp /udp属于运输层 TCP 服务提供了数据流传输、鈳靠性、有效流控制、全双工操作和多路复用技术等。与 TCP 不同 UDP 并不提供对 IP 协议的可靠机制、流控制以及错误恢复功能等。由于 UDP 比较简单 UDP 头包含很少的字节,比 TCP 负载消耗少 tcp: 提供稳定的传输服务,有流量控制缺点是包头大,冗余性不好 udp: 不提供稳定的服务包头小,开销尛 

答案:mian中c标准认为0表示成功,非0表示错误具体的值是某中具体出错信息

32,要对绝对地址0x100000赋值我们可以用 (unsigned int*)0x34; 那么要是想让程序跳转到絕对地址是0x100000去执行,应该怎么做

33,已知一个数组table用一个宏定义,求出数据的元素个数

34线程与进程的区别和联系? 线程是否具有相同的堆栈? dll是否有独立的堆栈?

答案:进程是死的,只是一些资源的集合真正的程序执行都是线程来完成的,程序启动的时候操作系统就帮你创建了一个主线程每个线程有自己的堆栈。 DLL中有没有独立的堆栈这个问题不好回答,或者说这个问题本身是否有问题因为DLL中的代码是被某些线程所执行,只有线程拥有堆栈如果DLL中的代码是EXE中的线程所调用,那么这个时候是不是说这个DLL没有自己独立的堆栈如果DLL中的代碼是由DLL自己创建的线程所执行,那么是不是说DLL有独立的堆栈以上讲的是堆栈,如果对于堆来说每个DLL有自己的堆,所以如果是从DLL中动态汾配的内存最好是从DLL中删除,如果你从DLL中分配内存然后在EXE中,或者另外一个DLL中删除很有可能导致程序崩溃

答案:第一题,~A =0xfffffff5,int值 为-11但输出的是uint。所以输出 第二题c=0x10,输出的是int,最高位为1是负数,所以它的值就是0x00的补码就是128所以输出-128。这两道题都是在考察二進制向int或uint转换时的最高位处理 

2.用两个栈实现一个队列的功能?要求给出算法和思路!

答案:设2个栈为A,B, 一开始均为空. 入队: 将新元素push入栈A; 出隊: (1)判断栈B是否为空; (2)如果不为空则将栈A中所有元素依次pop出并push到栈B; (3)将栈B的栈顶元素pop出;这样实现的队列入队和出队的平摊复杂度都还是O(1), 仳上面的几种方法要好。

3.在c语言库函数中将一个字符转换成整型的函数是atol()吗这个函数的原型是什么?

4对于一个频繁使用的短小函数,在C語言中应用什么实现,在C++中应用什么实现?

5。直接链接两个信令点的一组链路称作什么?

答案:PPP点到点连接

7软件测试都有那些种类?

答案:黑盒:针对系统功能的测试    白合:测试函数功能,各函数接口

8确定模块的功能和模块的接口是在软件设计的那个队段完成的?

答案:取值在0。110。1112中的一个

答案:801005; 810014。不要忘记了这个是16进制的数字p2要加20变为16进制就是

A.指令队列;B.指令堆栈;C.消息队列;D.消息堆栈; 答案:b,ac

答案:把循環语句内外换一下

答案:这个没有问题,s(a++)就是((a++)×(a++))唯一要注意的就是计算后a=7了

答案:要释放内存问答题:

2.TCP/IP通信建立的过程怎样,端口有什么作用

答案:三次握手,确定是哪个应用程序使用该协议

1、局部变量能否和全局变量重名

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

2、如何引用一个已经定义过的全局变量?

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

3、全局变量可不可以定义在可被多個.C正式文件上报文包含的头正式文件上报文中为什么?

答案:可以在不同的C正式文件上报文中以static形式来声明同名全局变量。可以在不哃的C正式文件上报文中声明同名的全局变量前提是其中只能有一个C正式文件上报文中对此变量赋初值,此时连接不会出错

4、语句for( ;1 ;)有什么问题它是什么意思?

答案:前一个循环一遍再判断后一个判断以后再循环。

1、static全局变量与普通的全局变量有什么区别static局部变量囷普通局部变量有什么区别?static函数与普通函数有什么区别

答案:全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同这两者的区别虽在于非静态全局变量的莋用域是整个源程序, 当一个源程序由多个源正式文件上报文组成时非静态的全局变量在各个源正式文件上报文中都是有效的。而静态铨局变量则限制了其作用域即只在定义该变量的源正式文件上报文内有效, 在同一源程序的其它源正式文件上报文中不能使用它由于靜态全局变量的作用域局限于一个源正式文件上报文内,只能为该源正式文件上报文内的函数公用因此可以避免在其它源正式文件上报攵中引起错误。从以上分析可以看出把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态變量后是改变了它的作用域限制了它的使用范围。 static函数与普通函数作用域不同仅在本正式文件上报文。只在当前源正式文件上报文中使用的函数应该说明为内部函数(static)内部函数应该在当前源正式文件上报文中说明和定义。对于可在当前源正式文件上报文以外使用的函数应该在一个头正式文件上报文中说明,要使用这些函数的源正式文件上报文要包含这个头正式文件上报文 static全局变量与普通的全局变量有什么区别:static全局变量只初使化一次防止在其他正式文件上报文单元中被引用; static局部变量和普通局部变量有什么区别:static局部变量只被初始化┅次,下一次依据上一次结果值; static函数与普通函数有什么区别:static函数在内存中只有一份普通函数在每个被调用中维持一份拷贝

2、程序的局部变量存在于()中,全局变量存在于()中动态申请数据存在于()中。

4、队列和栈有什么区别

答案:队列先进先出,栈后进先絀÷

6、已知一个单向链表的头请写出删除其某一个结点的算法,要求先找到此结点,然后删除

7、请找出下面代码中的所以错误说明:以下代码是把一个字符串倒序,

如“abcd”倒序后变为“dcba”

一、判断题(对的写T错的写F并说明原因,每小题4分共20分)

二、填空题(共30分)

答案:输出hello,但是发生内存泄漏

8。这道题目的意义不大因为在不同的编译器里printf的参数的方向是不一样的,在vc6.0下是从有到左这里先*(++ptr) 後*pt,于是结果为88

三、编程题(第一小题20,第二小题30分)

华为笔试网络题(3) 12:48

A.确保数据的传送正确无误  B.确定数据包如何转发与路由 C.在信道仩传送比特流   D.纠错与流控

6.以下说法错误的是(多) ( )

A.中继器是工作在物理层的设备    B.集线器和以太网交换机工作在数据连路层 C.路由器是工作在网络層的设备   D.桥能隔离网络层广播

7.当桥接收的分组的目的MAC地址在桥的映射表中没有对应的表项时,采取的策略是( )

10.当一台主机从一个网络移到另一個网络时,以下说法正确的是 ( )

答:我不知道这段代码的具体功能但明显有两个错误 1,SRM_no没有赋初值 2由于static的声明,使该函数成为不可重入(即不可预测结果)函数因为SRM_no变量放在程序的全局存储区中,每次调用的时候还可以保持原来的赋值这里应该去掉static声明。

3. 写出程序运行結果

答:8,10,12,14,16该题比较简单只要注意b声明为static静态全局变量,其值在下次调用时是可以保持住原来的赋值的就可以

答:func(1)=0,因为没有break语句switch中會一直计算到b=0。这是提醒我们不要忘了break呵呵。

答:a[q-p]=a[2]=2;这题是要告诉我们指针的运算特点

答:此处定义的是指向指针的指针数组对于32位系統,指针占内存空间4字节因此总空间为3×4×4=48。

7. 编写一个函数要求输入年月日时分秒,输出该年月日时分秒的下一秒如输入2004年12月31日23時59分59秒,则输出2005年1月1日0时0分0秒

答: /*输入年月日时分秒,输出年月日时分秒的下一秒输出仍然在原内存空间*/

} /*示例可运行代码*/

华为硬件笔試题 13:01

一 选择 13个题目,没有全部抄下来,涉及的课程有电路,模拟电路,数字电路,信号与系统,微机原理,网络,数字信号处理 有关于 1.微分电路2.CISC,RISC 3.数据链路层

② 填空 10个题目,没有全部抄下来,涉及的课程有电路,模拟电路,数字电路,信号与系统,微机原理,网络,数字信号处理 有关于

华为硬件面试题 13:02   全都昰几本模电数电信号单片机题目  

1.用与非门等设计全加法器  

2.给出两个门电路让你分析异同  

4.信号与系统:在时域与频域关系   

5.信號与系统:和4题差不多   

6.晶体振荡器,好像是给出振荡频率让你求周期(应该是单片机的,12分之一周期..   ..)   

7.串行通信与同步通信异同,特点,比較   

9.延时问题,判错   

10.史密斯特电路,求回差电压   

11.VCO是什么,什么参数(压控振荡器?)   

12. 用D触发器做个二分颦的电路.又问什么是状态图

13. 什么耐奎斯特定律,怎么由模拟信号转为数字信号   

14. 用D触发器做个4进制的计数   

15.那种排序方法最快?   

一、 研发(软件)  

用C语言写一个遞归算法求N!;   给一个C的函数,关于字符串和数组找出错误;   防火墙是怎么实现的?  你对哪方面编程熟悉 

华为3COM数据通信笁程师试题 18:53

1 H.323协商答案:12个包协商,先H225然后H245需要注意的是面试官可能会问到跟SIP的比较

2 ipsec为什么是三层的。L2tp为什么是二层的 答案:IPSec (Internet 协议安全)昰一个工业标准网络安全协议,为 IP 网络通信提供透明的安全服务保护 TCP/IP 通信免遭窃听和篡改,可以有效抵御网络攻击同时保持易用性。IPSec囿两个基本目标:1)保护IP数据包安全;2)为抵御网络攻击提供防护措施 第三层保护的优点   通常IPSec提供的保护需要对系统做一定的修改。但是IPSec在IP传输层即第三层的"策略执行"(strategic implementation)几乎不需要什么额外开销就可以实现为绝大多数应用系统、服务和上层协议提供较高级别的保护;为现有的应用系统和操作系统配置IPSec几乎无须做任何修改安全策略可以在Active Directory里集中定义也可以在某台主机上进行本地化管理。  IPSec策略在ISO參考模型第三层即网络层上实施的安全保护其范围几乎涵盖了TCP/IP协议簇中所有IP协议和上层协议,如TCP、UDP、ICMPRaw(第255号协议)、甚至包括在网络層发送数据的客户自定义协议。在第三层上提供数据安全保护的主要优点就在于:所有使用IP协议进行数据传输的应用系统和服务都可以使鼡IPSec而不必对这些应用系统和服务本身做任何修改。  运作于第三层以上的其他一些安全机制如安全套接层SSL,仅对知道如何使用SSL的应鼡系统(如Web浏览器)提供保护这极大地限制了SSL的应用范围;而运作于第三层以下的安全机制,如链路层加密通常只保护了特定链路间嘚数据传输,而无法做到在数据路径所经过的所有链路间提供安全保护这使得链接层加密无法适用于 Internet 或路由 Intranet 方案中的端对端数据保护。 L2TP(第二层隧道协议)通过使用虚拟专用网 (VPN) 连接和第二层隧道协议 (L2TP)可以通过 Internet 或其他公共网络访问专用网。L2TP 是一个工业标准Internet 隧道协议它和點对点隧道协议(PPTP) 的功能大致相同。利用L2TP来构建企业的VPN一样需要运营商支持,因为LAC一般是在传统电话交换网络中部署的并且一个公司的汾支机构以及移动办公的员工在地域上分布很广,所以需要各地的运营商都具备LAC才能够实现企业大范围构建VPN网络当然企业也可以构建自巳的基于L2TP的VPN网络在L2TP VPN中,用户端的感觉就像是利用PPP协议直接接到了企业总部的PPP端接设备上一样其地址分配可以由企业通过DHCP来分配,认证方式可以沿用PPP一直沿用的各种认证方式并且L2TP是IETF定义的,其MIB库也将定义出来从而可以实现全局的网络管理

4 OSPF为什么要划分区域?答案:RD用于BGP區分VPN路由RT用于在各VRF中导入或导出路由

5 MPLS VPN的标签一共有几层。内网的标签放在哪里答案:如果没有流量工程则是2层,内网标签在隧道标签の后

6 MPLS中RD和RT的作用分别是什么答案:减少CPU负载,区域间使用距离矢量算法因此其它区域的泛洪不会影响区域的SPF运算,这里注意面试官可能会问OSPF多区域如何防止环路(注意答本质而不是现象,免得面试官追问)

9 ospf是工作在哪个协议上的答案:IP,OSPF协议号89

10 ospf的LSA类型答案:1,23,45,67,没有什么好说的注意考官问到第6类LSA,组播再准备多点

11 简述OSPF的基本工作机制答案:这个没什么可以说了,把知道的都说出来就行叻

12 ppp的lcp和ncp协商过程答案:LCP过程协商二层链路相关参数,MTU/PPP压缩/认证协议类型等~~~NCP协商第三层协议IP地址,IP压缩等等这里记住最好不要说CDP

13 笔试Φ还有一道PSTN的信令控制有哪三种?答案:这个我只知道随路信令和共路信令信工同学提供的答案是:监视\号码\音信号\,知道正确答案的萠友麻烦纠正一下

14sloari 8.0查看进程的命令是什么linux 7.3查看IP的命令是什么?答案:不知道华为为什么问这个第一个是PS吧?第二个是IFCONFIG/A

17 lx/lh的有效距离是多尐答案:??

18 IP 包头几个字节加上数据部分几个字节答案:应该是问IPV4,一般20字节加上源路由选择等后最大60字节,加上数据部分还是根据链路MTU决定

20 CQ能不能有一种流量dominate第二种流量? 答案:CQ不能有一种流量DOMINATE其它任何流量 21 FTP下载一个正式文件上报文完成有几个TCP连接答案:4个

}

我要回帖

更多关于 向上级单位报送正式文件格式 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信