VC调试习题详解02
- 格式:doc
- 大小:823.55 KB
- 文档页数:38
VC++6.0 调试详细教程Step intoStep overStep outRun to cursorWatchVariablesRegistersMemoryStop DebugCall stackDisassemblyRestart Debugger2、调试的一般过程调试,就是在程序的运行过程的某一阶段观测程序的状态。
在一般情况下程序是连续运行的,所以我们必须使程序在某一地点停下来。
我们所做的第一项工作就是设立断点;其次再运行程序;当程序在设立断点处停下来时,利用各种工具观察程序的状态。
程序在断点停下来后,有时我们需要按我们的要求控制程序的运行,以进一步观测程序的流向。
下面我们依次来介绍断点的设置,如何控制程序的运行以及各种观察工具的利用。
3、设置断点在VC中,可以设置多种类型的断点,根据断点起作用的方式把这些断点分为三类:1、与位置有关的断点;2、与逻辑条件有关的断点3、与WINDOWS消息有关的断点。
主要介绍前面两种断点。
4、设置位置断点最简朴的是设置一般位置断点:? 把光标移到你要设断点的位置,当然这一行必须包含一条有效语句的;? 然后按工具条上的add/remove breakpoint 按钮或按快捷键F9。
将会在屏幕上看到在这一行的左边出现一个红色的圆点表示这里设立了一个断点5、设置位置断点6、设置逻辑断点有的时候可能不需要程序每次运行到这儿都停下来,而是在满意一定条件的情况下才停下来,这时就需要设置一种与位置有关的逻辑断点。
从EDIT 菜单中选中Breakpoints命令,这时Breakpoints对话框将会出现在屏幕上。
选中Breakpoint对话框中的Location标签,使Location页面弹出。
8、设置逻辑断点单击上页Condition按钮,弹出Breakpoint Condition对话框,在expression_r_r编辑框中写出你的逻辑表达式,最后按OK返回。
1.调试 C 程序时常见的错误类型分析一般情况下,错误主要分为两大类:一、语法错误。
对于这种错误,用编译器很容易解决。
所以,改错题的第一步是先编译,解决这类语法错误。
下面总结了二级C 语言上机改错题中常见的语法错误:(1) 丢失分号,或分号误写成逗号。
(2) 关键字拼写错误,如本来小写变成大写。
(3) 语句格式错误,例如for 语句中多写或者少写分号。
(4) 表达式声明错误,例如:少了()(5) 函数类型说明错误。
与main ()函数中不一致。
(6) 函数形参类型声明错误。
例如:少* 等。
(7) 运算符书写错误,例如:/ 写成了。
二、逻辑错误,或者叫语义错误,这和实现程序功能紧密相关,一般不能用编译器发现。
对于逻辑错误可以按这样的步骤进行查找。
(1) 先读试题,看清题目的功能要求。
(2) 通读程序,看懂程序中算法的实现方法。
(3) 细看程序,发现常见错误点。
2.改错题的改错方式总结,当然这些总结只能对大部分改错行有效1、若错误行是函数首部,可分为以下几种情况:A、该行最后若有分号则删除,中间若有分号则改成逗号B、形参类型不一致的问题,特别是指针类型,若后面用到某形参时有指针运算则该形参必为指针类型;若形参是二维数组或指向m 个元素的指针变量,则第二维的长度必须与main 中对应数组的第二维长度相同C、函数类型不一致的问题,若函数中没有return语句则函数类型为void,若有return语句则函数的类型必须与return 后变量的类型一致。
2、若错误行是if 或while 语句,则首先看有没有用小括号将整个表达式括起,若没有则加上小括号。
3、若错误行中有if、while 、for 则要特别注意条件表达式的错误问题:A、指针变量的应用,若表达式中有指针变量且没有指针运算符,则加上指针运算符B、若条件表达式中只有一个等于号,则改成两个等于号,若为其它比较运算符则一般是进行逆转或加一个等于号C、f or 中要用分号分隔表达式,而不是用逗号4、语法错误A、语句缺少分号,若错误行中有语句没有用分号结束,则加上分号。
单选题(10*2分=20分)1.在C++中,若对函数类型未加说明,则函数的隐含类型是()A、voidB、doubleC、intD、char2.系统在调用重载函数时往往根据一些条件确定哪个重载函数被调用。
在下列选项中,不能作为依据的是()A、参数个数B、参数的类型C、函数名称D、函数的类型3. 若有以下定义,则对b数组元素正确的引用是()Int b[2][3]={1,2,3,4,5,6};A、b[1]B、b[0][3]C、b[2][2]D、b[1][1]4.下述程序片段的输出是()int a[3][4]={{1,2,3,4},{5,6,7,8}};int x,*p=a[0];x=(*p)*(*p+2)*(*p+4);cout<<x<<endl;A、15B、14C、16D、135. 下面四个MFC类中哪一个是管理MFC应用程序的( )A. CWinAppB. CMainFrameC. CDocumentD. CView6. 下列类中不属于MFC框架基本类的是( )A. CWinAppB. CFrameWndC. CViewD. CObject7.以下四个关于类的访问控制的描述哪一个是错误的( )A.子类不能访问其父类的私有数据成员和成员函数B.子类的对象不能访问其父类的保护数据成员或者成员函数C.类的对象不能访问类的保护数据成员或者成员函数D.类的成员函数不能访问类中的私有数据8. 更新菜单状态的消息是()。
A. WM_COMMANDB. UPDA TEC. ON_UPDA TE_COMMAND_UID.INV ALIDATE9. 所有的控件都是( ) 类的派生类,都可以作为一个特殊的窗口来处理。
A. CViewB. CWndC. CWindowD. CDialog10. 视图类中支持绘图的成员函数是()A.OnDraw B.OnInitUpdate C.OnSize D.OnLButtonDown二、填空题(10分)1、类的访问权限有__________、__________和__________3种。
第1章用MFC开发Windows应用程序习题1.安装Visual C++.Net集成开发环境。
2.启动Visual C++ .Net集成开发环境,熟悉其菜单、工具栏和窗口的操作过程。
3.模仿书中的例子,编写“Hello,Visual C++ .Net”程序。
4.编写程序,在窗口中输出两行由字符“*”组成的字符串,中间是“爱国爱校、追求真理、勤奋踏实、艰苦朴素”。
第2章窗口类和消息处理机制习题1.设计一个应用程序,当单击鼠标左键时,窗口中显示“鼠标左键按下”;当单击鼠标右键时,窗口中显示“鼠标右键按下”。
解答:void CB01View::OnLButtonDown(UINT nFlags, CPoint point){CDC *pDC=GetDC();pDC->TextOut(10,10,_T("鼠标左键按下"));CView::OnLButtonDown(nFlags, point);}void CB01View::OnRButtonDown(UINT nFlags, CPoint point){CDC *pDC=GetDC();pDC->TextOut(10,10,_T("鼠标右键按下"));CView::OnRButtonDown(nFlags, point);}2.在窗口上绘制一个正方形,当鼠标单击它时,可以在客户区中任意拖动。
解答:在View类中添加下列变量:CRect rect;bool capture;CPoint old;在View类构造函数添加初始化代码:capture=false;rect=CRect(0,0,100,100);添加鼠标左键按下、左键释放以及鼠标移动消息处理函数,并添加处理代码,函数如下:void CMy2_2View::OnLButtonDown(UINT nFlags, CPoint point){// TODO: Add your message handler code here and/or call defaultif(rect.PtInRect(point)){capture =true;old=point;}CView::OnLButtonDown(nFlags, point);}void CMy2_2View::OnMouseMove(UINT nFlags, CPoint point){// TODO: Add your message handler code here and/or call defaultif(capture){CSize sz=point-old;rect=rect+sz;old=point;this->Invalidate();}CView::OnMouseMove(nFlags, point);}void CMy2_2View::OnLButtonUp(UINT nFlags, CPoint point){// TODO: Add your message handler code here and/or call defaultcapture =false;CView::OnLButtonUp(nFlags, point);}在OnDraw函数中添加一行代码:pDC->Rectangle(rect);3.编写一个程序,在窗口显示一个实心圆,圆自动从窗口左端移动到窗口右端。
2.5 习题1.填空题(1) MFC的全称是 Microsoft Foundation Class 。
(2) Windows是一个基于事件的消息驱动系统。
(3) 句柄是Windows使用的一种无重复整数,主要用来标识应用程序中的一个对象。
(4) 利用MFC AppWizard[exe]可以创建三种类型的应用程序,即单文档、多文档和基于对话框的应用程序。
(5) 一个单文档的MFC应用程序框架一般包括5个类,它们分别是应用程序类、框架窗口类、视图类、文档类和文档模板类。
(6) Windows消息主要有3种类型,即标准Windows消息、控件消息和命令消息。
(7) MFC采用消息映射来处理消息。
(8) CWinApp提供4个成员函数来实现传统SDK应用程序WinMain( )函数完成的工作。
2.选择题(1) Windows应用程序是按照()非顺序的机制运行的。
A.事件→消息→处理B.消息→事件→处理C.事件→处理→消息D.以上都不对(2) 下面( )不是MFC应用程序外观的选项。
A.Docking toolbar B.Context-sensitive HelpC.ActiveX Controls D.Printing and print preview(3) 对MFC类的下列描述中,( )是错误的。
A.应用程序类CWinApp是CWinThread的子类B.窗口类CWnd提供了MFC中所有窗口类的基本功能C.CView是CWnd类的子类D.CDocTemplate类是Template类的子类(4) 下列( )不是MFC消息映射机制有关的宏。
A.DECLARE_MESSAGE_MAP( )宏B.BEGIN_MESSAGE_MAP( )宏C.DECLARE_SERIAL( )宏D.END_MESSAGE_MAP( )宏(5)利用ClassWizard不能(D)A.建立新类 B.进行消息映射C.增加类的成员变量 D。
VC调试篇 -管理资料2019-01-01难怪很多前辈说调试是一个程序员最基本的技能,其重要性甚至超过学习一门语言,。
不会调试的程序员就意味着他即使会一门语言,却不能编制出任何好的软件。
我以前接触的程序大多是有比较成形的思路和方法,调试起来出的问题都比较小,最近这个是我自己慢慢摸索调试,接触了很多新的调试方法,并查了很多前辈的,受益匪浅,总结以前的和新的收获如下:VC调试篇设置为了调试一个程序,首先必须使程序中包含调试信息。
一般情况下,一个从AppWizard创建的工程中包含的Debug Configuration自动包含调试信息,但是是不是Debug版本并不是程序包含调试信息的决定因素,程序设计者可以在任意的Configuration中增加调试信息,包括Release版本。
为了增加调试信息,可以按照下述步骤进行:打开Project settings对话框(可以通过快捷键ALT+F7打开,也可以通过IDE菜单Project/Settings打开)选择C/C++页,Category中选择general,则出现一个Debug Info下拉列表框,可供选择的调试信息方式包括:命令行Project settings说明无None没有调试信息/ZdLine Numbers Only目标文件或者可执行文件中只包含全局和导出符号以及代码行信息,不包含符号调试信息/Z7C 7.0- Compatible目标文件或者可执行文件中包含行号和所有符号调试信息,包括变量名及类型,函数及原型等/ZiProgram Database创建一个程序库(PDB),包括类型信息和符号调试信息。
/ZIProgram Database for Edit and Continue除了前面/Zi的功能外,这个选项允许对代码进行调试过程中的修改和继续执行。
这个选项同时使#pragma设置的优化功能无效选择Link页,选中复选框"Generate Debug Info",这个选项将使连接器把调试信息写进可执行文件和DLL如果C/C++页中设置了Program Database以上的选项,则Link incrementally 可以选择。
类编程题1.【题目】试定义一个类NUM,验证下列命题是否成立:任意一个正整数与其反序数相加,得到一个新的正整数,再对这个新正整数重复上述步骤,最终一定可以得到一个回文数。
例如,正整数350的反序数为053(即53),350+53=403,403+304=707,707是回文数,命题成立。
又如,正整数2015的反序数为5102,2015+5102 =7117,7117是回文数,命题成立。
具体要求如下:私有数据成员int num:存放用于验证命题的正整数。
公有成员函数NUM(int x):构造函数,用x初始化数据成员num。
void set(int a):将num的值设置为a。
int yn(int n):判断n是否回文数,若是,返回1;否则返回0。
void fun():使用num验证命题是否成立,并显示验证过程。
在主函数中对该类进行测试。
输出示例:num=350的验证过程如下:350+53=403403+304=707命题成立!num=2015的验证过程如下:2015+5102=7117命题成立!#include <>class NUM{private:int num;public:NUM(int x);void set(int a);int yn(int n);void fun();};NUM::NUM(int x){num=x;}void NUM::set(int a){num=a;}int NUM::yn(int n){int t=n,s=0;while(t){s=s*10+t%10;t/=10;}if(s==n) return 1;else return 0; }void NUM::fun(){int m;cout<<"num="<<num<<"的验证过程如下:"<<endl;while(1){int n=num,s=0; verall<st[j].overall) {int t; t=st[i].overall;st[i].overall=st[j].overall;st[j].overall=t;}}void STU::print(){cout<<name<<'\t'<<norm<<'\t'<<ex<<'\t'<<final<<'\t'<<overall<<endl;}void main(){STU s[3];char name[100];int norm,ex,fin;for(int i=0;i<3;i++) {cout<<"请输入姓名、平时成绩、实验成绩、期末成绩:"<<endl;cin>>name>>norm>>ex>>fin;s[i].init(name,norm,ex,fin);s[i].fun();}cout<<"按总评成绩排序后:\n姓名平时成绩实验成绩期末成绩总评成绩"<<endl;sort(s,3);for(i=0;i<3;i++) {s[i].print();}}3.【题目】试定义一个类Array,首先求各列元素中的合数(非素数)之和,再将数组各列以其合数之和的大小从大到小排序,具体要求如下:(1) 私有数据成员int a[4][5]:需要排序的二维数组。
Visual C++面向对象与可视化程序设计 习题第1章【1-1】C++语言的基本数据类型包含哪些?【1-2】C++语言中函数的作用是什么?【1-3】C++语言中的指针有哪些类型?它们都如何定义?【1-4】在C++语言中如何进行“类”的定义?【1-5】构造函数和析构函数的功能是什么?如何创建构造函数和析构函数?【1-6】C++语言中“派生”的含义是什么?【1-7】C++语言中重载的作用是什么第2章【2-1】 在VC++6.0环境中如何创建Project文件?【2-2】 如何利用VC的资源编辑器【2-3】 如何充分利用VC提供的丰富的联机帮助功能?第3章【3-1】Windows编程中窗口的含义是什么?【3-2】 事件驱动的特点是什么?【3-3】 Windows应用程序中的消息传递是如何进行的?请举例说明。
【3-4】 句柄的作用是什么?请举例说明。
【3-5】Windows应用程序最基本构成应有哪些部分?【3-6】 应用Windows API函数编程时有什么特点?第4章【4-1】 什么是图形设备接口?【4-2】 如何进行图形的刷新?【4-3】 如何获取绘图工具的句柄?【4-4】 如何定义映射模式?【4-5】 请编写程序,要求如下:(1)定义一只红色的画笔,绘制一个等边五边形(2)用不同颜色的线条连接互不相邻的两个点(3)用不同颜色的画刷填充用上述方法所形成的图形中的每一个区域【4-6】 编写一个程序,在屏幕上出现一个圆心沿正弦曲线轨迹移动的实心圆,而且,每隔四分之一周期,圆的填充色和圆的周边颜色都发生变化(颜色自己选取),同时,圆的半径在四分之一周期之内由正弦曲线幅值的0.2倍至0.6倍线性增长【4-7】如图4-2,分别调用系统定义的四种笔样式PS_DOT, PS_DASHDOT, PS_DASHDOTDOT, PS_DASH画出四个圆,看一看有什么差别。
然后调用系统定义的6种实画刷画出矩形,调用系统定义的6种阴影画刷来画出圆角矩形。
1.VC++ 6.0 的调试功能简介常用功能:Restart(Ctrl+shift+F5):此debugger功能将从程序的开始(第一有效行)处全速执行,而不是从当前所跟踪的位置开始调试,这时所有变量的当前值都将被丢弃,debugger会自动停在程序的main()开始处.这时如果选择Step Over(F10)就可以逐步执行main()函数了.Stop Debugging(Shift+F5):此debugger功能将终止(所有)调试,并返回到常规编辑状态.Break(此功能常常在遇到调用函数的语句时可见.):此功能将在调试过程中的debugger 当前位置挂起程序的执行,然后就可以在调试状态一修改程序的代码,接着可以用Apply Code Changes(Alt+F10)来应用修改的代码到正在调试的程序当中.如果,当前(需要,待)可以(从DOS等窗口)输入值,挂起后将不能再输入.Apply Code Changes(Alt+F10):此功能可以在程序正在调试程序过程中应用(挂起)修改后的源代码.如,选择Break功能并修改代码后,只要选择Apply Code Changes(Alt+F10)就能将修改后的代码应用到正在调试的程序当中.Show Next Statement(Alt+Num*):此功能将显示程序代码的下一条语句,如果源代码中找不到,则在Disassembly窗口中显示语句.当在Disassembly窗口中显示时,可以单击Disassembly 返回到源代码窗口.Step Into(F11):此功能可以单步进入到在调试过程中所跟踪的调用函数的语句的函数内部.如,当前语句是"d.Display()",选择Step Into(F11)后,Debugger将进入Display()函数内部并停在Display()函数内部的第一条语句上.(此时,就可以Step Over(F10)对Display()函数进行单步调试了.)Step Over(F10):此功能可以单步对所在函数单步调试,如果调试的语句是一个调用函数的语句时,Debugger将全速执行所调用的函数,单步(一步)通过所调用的函数,Debugger停该调用语句的下一条语句上.Step Out(Shift+F11):此功能将使Debugger切换回全速执行到被调用函数结束,并停在该函数调用语句的下一条语句上.当确定所调用的函数没有问题时可以用这个功能全速执行被调用函数.Run to Cursor(Ctrl+F10):此功能将全速执行到包含插入点光标所在的行,可以作为在插入点光标处设置常规断点的一种选择.注意,当光标处不是一个有效的执行语句时此功能将不起作用.Go(F5):此功能将全速执行程序直到遇到一个断点或程序结束,或直到程序暂停等待用户输入.注意,此功能最能有效的调试循环,常将断点设置在循环体内,重复的按F5全速执行循环体可以测试循环过程中的产生的变化.Step Into Specific Function:此功能可以可以单步通过程序中的指令,并进入指定的函数调用,此功能对于函数的嵌套层不限.变量(Variable)变量窗口提供快捷的方式对程序当前上下文变量进行访问。
该窗口包括三个选项卡:自动(Auto):显示当前语句和前一语句中使用的变量,同时也显示在步越(Step Over)或步出(Step Out)一个函数时的返回值。
局部(Local):显示当前函数中的局部变量。
本对象(this):显示this所指向的对象。
除了标签,该窗口的工具条上还有一个下来列表-上下文列表(Context),其中包含当前调用栈的拷贝。
选择不同上下文,可以浏览不同的程序内容。
快速查看(QuickWatch)快速查看对话框包含一个文本框,在其中输入表达式或变量的名称,以及一个表格显示该变量或表达式的当前值。
如果在Value文本框中键入新值或表达式然后按回车键,则当前值表格中的内容将被替换。
程序也将受其影响。
快速查看将显示变量的缺省格式,但是可以使用格式符号来改变显示格式(如显示大写字符集Unicode)。
查看(Watch)使用Watch窗口可以查看窗口指定变量或表达式,也可以修改相应的变量值。
查看窗口包含四个选项卡: Watch1、Watch2、Watch3、Watch4。
它们之间没什么分别。
查看窗口并不显示变量的类型,但是可以用窗口属性来显示当前选中变量的类型。
内存(Memory)使用内存窗口可以对特定内存区域的内容进行浏览。
在Address地址栏键入内存地址,如0x12ffc0,按回车即可查看。
寄存器(Registers)寄存器窗口使程序员可以实时的观察寄存器的变化,掌握程序运行的最细节内容。
寄存器一般与反汇编显示配合使用。
调用栈(CallStack)在调试状态下,调用栈窗口显示当前正在使用的函数调用堆栈。
当调用一个函数时,它将被压入堆栈,而在返回时,又从堆栈中弹出。
于是函数堆栈中显示的就是一个调用嵌套表,是当前一系列未执行完的函数。
通过调用栈窗口可以浏览函数的源代码或反汇编对象代码。
反汇编(Disassembly)反汇编窗口在经过反汇编的指令上操作,而不是源代码语句或行。
使用反汇编窗口可以在任何指令上设置断点,如果步入(Step Into)或步越(Step Over)反汇编窗口所示语句,调试器将逐条执行指令,而不是逐行执行。
反汇编窗口设为可拼借窗口形式时(Docking View)时,就可以仍以源代码窗口为主,其他调试窗口为辅助进行调试。
调试常用快捷键单步进入F11单步跳过F10单步跳出SHIFT+F11运行到光标CTRL+F10开关断点F9清除断点CTRL+SHIFT+F9Breakpoints(断点管理)CTRL+B 或ALT+F9GO F5Compile(编译,生成.obj文件)CTRL+F7Build(组建,先Compile生成.obj再Link生成.exe)F72.当第一次把szName1值改之后到第二次输出前并没有改szName1的值,为什么俩次输出结果不一样?#include <stdio.h>#include <string.h>int main(int argc, char* argv[]){char szName1[10];char szName2[4];int i = 0, b = 0;strcpy(szName1,"shenzhen");printf("%s\n",szName1);strcpy(szName2,"vckbase");printf("%s\n",szName1);printf("%s\n",szName2);return 0;}解答:你可能认为是:shenzhenshenzhenvckbase但实际结果为:shenzhenasevckbase如果你觉得无从下手的时候,对于这样简短的程序,你可以选择单步调试!首先把光标移动到第一个strcpy的那行上,然后按F9 或点击编译器上的手型标记如右图或右击鼠标选择insert/remove breakpoint 去添加断点,如下图:图2.1接着按F5或点击编译器上的Go 图标如右图,就会转向如下状态:图2.2此时可通过memory窗口查看和监视数组szName1和szName2内存中实际的值!但内存窗口需要变量的开始地址方能查看,所以必须要知道数组szName1和szName2的首地址,此需求可通过watch窗口查看。
方法如下:如果你的watch 窗口没有打开,则点击编译器上的watch图标:如右图:然后把你要查看的变量的名字输入到Name栏中,也可通过鼠标从代码编辑窗口中拖入到watch窗口中。
结果如下图:图2.3此时Value栏下的值就是数组szName1和szName2的地址。
分别是0x0012ff74和0x0012ff70。
然后把地址输入到memory 窗口中。
如果没有显示memory 窗口,在点击编译器上的memory按钮如右图:。
由于memory窗口中从左到右,从上到下是地址值增长的方向,故为了方便查看这俩个数组的内存,把俩个数组中地址低的地址值输入,按回车键查看。
如下如图所示:图2.4图中红框圈住的10个字节就是szName1的内存,用蓝方框圈住的4个就是szName2的内存。
单步跳过一行:按F10 或点击编译器的按键,如右图:。
然后查看各个监视窗口的状态。
如下图:图2.5图2.6图2.7首先解释一下图2.6中”shenzhen”“烫烫shenzhen”的意思,其实这是编译器的自动翻译,起一个提示作用,它是从0x0012ff74这个地址开始,把每个内存中的数据按字符显示而已,知道遇到’\0’为止,因此显示出的是一个字符串,用””表示。
下面的烫烫是,显示为汉字它是把俩个字节数据组合翻译成一个汉字。
因为汉中要占俩个字节。
而图2.7中的... 是代表编译器不知道要把当前内存中的数据翻译成什么字符,故用. 表示。
单步跳过一行:即执行printf("%s\n",szName1); 语句。
即从地址0x0012ff74开始,到遇到’\0’结束,把每一个内存中的数据解析为一个字符输出,然后输出一个字符串shenzhen。
如下图:图2.8单步跳过一行:即执行strcpy(szName2,"vckbase"); 即把字符串,"vckbase"拷贝到从地址0x0012ff70开始的内存中。
如下图:图2.9单步跳过一行:即执行printf("%s\n",szName1); 即从地址0x0012ff74开始,到遇到’\0’结束,把每一个内存中的数据解析为一个字符输出,然后输出一个字符串。
结果为ase其实从图2.9可以看出。
如下图:图2.10从s初开始,到e结束,对应的字符即为右边红框中的内容。
单步跳过一行:即执行printf("%s\n",szName2); 即从地址0x0012ff70开始,到遇到’\0’结束,把每一个内存中的数据解析为一个字符输出,然后输出一个字符串。
结果为vckbase其实从图2.9可以看出。
如下图:图2.10从s初开始,到e结束,对应的字符即为右边红框中的内容。
从上述分析之后,结果就正好是输出的结果,而不是你想象的那种。
看到这些之后,你可能就会得到如下结论:szName2数组只有四个大小,但是在从它的首地址开始给它拷贝字符串的时却多于4个,就是把它后面的内存给覆盖了,拷贝的结束是依’\0’为标记的,并且’\0’会拷贝到内存中,反之在读取数据是也是一样,从一个地址开始,并不是根据存放它的数组的大小决定字符串的长度,而是根据’\0’决定,即直到第一次看到某字节内存中的值为0x00时才停止,所以很容易越界访问,在写内存的时候可能会影响到其他内存的数据,从而影响到其他变量的值。