C/C++ 中 NULL、'\0'、'0' 、0及空格的区别

1、NULL即空指针。在C中,NULL是指向0的指针,由 #define NULL ((void *)0)定义;在C++中,NULL就是0,由 #define NULL 0 定义。可参见 vs2013 的库文件 string.h。

2、'\0' 是空字符常量,表示字符串的结束,ASCII码值为0。

3、'0'是字符0,ASCII码值为48。

4、0是数字0。用字符变量接收数字0时,相当于ASCII码为0的字符即空白符'\0'。

5、空格是可显示字符空格,ASCII 码值为32。

 

备注:

  给指针置位为空指针时,应该使用 NULL;

  给字符串添加结束标志时,应该使用 '\0' 。

       空字符串""中每个元素都是空白符'\0'。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目 录 1. 概述 3 1.1 实训项目简介 3 1.2 实训功能说明 3 1.2.1 基本功能 3 1.2.2 附加功能 3 2. 相关技术 4 2.1 Windows定时器技术 4 2.2 透明贴图实现技术 4 2.3 CObList链表 5 2.4获取矩形区域 6 2.5使用AfxMessageBox显示游戏过程的提示信息 6 2.6内存释放 6 2.7 CImageList处理爆炸效果 6 2.8对话框的应用 6 3. 总体设计与详细设计 7 3.1 系统模块划分 7 3.2 主要功能模块 8 3.2.1 系统对象类图 8 3.2.2 系统主程序活动图 9 3.2.3 系统部分流程图 9 4. 编码实现 12 4.1 绘制游戏背景位图程序 12 4.2 飞机大战游戏对象的绘制程序 13 4.3 飞机大战游戏对象战机位置的动态控制 15 4.4 飞机大战游戏对象之间的碰撞实现 17 4.5 游戏界面输出当前信息 19 5. 项目程序测试 20 5.1战机移动及子弹发射模块测试 20 5.2 敌机及炸弹模块测试 20 5.3 爆炸模块测试 20 6. 实训遇到的主要问题及解决方法 21 7. 实训体会 21 1. 概述 1.1 实训项目简介   本次实训项目是做一个飞机大战的游戏,应用MFC编程,完成一个界面简洁流畅、游戏方式简单,玩起来易于上手的桌面游戏。该飞机大战项目运用的主要技术即是MFC编程的一些函数、链表思想以及贴图技术。 1.2 实训功能说明 1.2.1 基本功能   (1)设置一个战机具有一定的速度,通过键盘,方向键可控制战机的位置,空格键发射子弹。   (2)界面敌机出现的位置,以及敌机炸弹的发射均为随机的,敌机与敌机炸弹均具有一定的速度,且随着关卡难度的增大,数量和速度均增加。   (3)对于随机产生的敌机和敌机炸弹,若超过矩形区域,则释放该对象。   (4)添加爆炸效果,包括战机子弹打敌机爆炸、敌机炸弹打战机爆炸、战机与敌机相撞爆炸以及战机子弹与敌机炸弹相撞爆炸四种爆炸效果。且爆炸发生后敌机、子弹、炸弹均消失,战机生命值减一。 1.2.2 附加功能   (1) 为游戏界面添加了背景图片,并在战机发射子弹、战机击敌机、敌机击战机、以及战机敌机相撞时均添加了背景音效。   (2)为游戏设置了不同的关卡,每个关卡难度不同,敌机与敌机炸弹的速度随着关卡增大而加快,进入第二关以后敌机从上下方均会随机出现,且随机发射炸弹。   (3)第一关卡敌机从上方飞出,速度一定,战机每打掉一直敌机则增加一分,每积十分,则为战机增加一个生命值,当战机得分超过50分则可进入下一关;进入第二、三关时敌机速度加快,分别从上下两方飞出,此时战机每得分20、30分,才会增加一个生命值,得分超过100、150分则进入下一关、通关。   (4) 在游戏界面输出当前游戏进行信息,包括当前得分、当前关卡以及击敌机数量。   (5)增加了鼠标控制战机位置这一效果,战绩的位置随着鼠标的移动而移动,并且点击鼠标左键可使得战机发射子弹。   (6)实现了暂停游戏的功能,玩家可通过键盘上的‘Z’键,对游戏进行暂停。   (7)通过对话框的弹出可提示玩家是否查看游戏说明、是否进入下一关、是否重新开始等消息,使得玩家可自己选择。 2. 相关技术 2.1 Windows定时器技术   Windows定时器是一种输入设备,它周期性地在每经过一个指定的时间间隔后就通知应用程序一次。程序将时间间隔告诉Windows,然后Windows给您的程序发送周期性发生的WM_TIMER消息以表示时间到了。本程序使用多个定时器,分别控制不同的功能。在MFC的API函数使用SetTimer()函数设置定时器,设置系统间隔时间,在OnTimer()函数实现响应定时器的程序。 2.2 透明贴图实现技术   绘制透明位图的关键就是创建一个“掩码”位图(mask bitmap),这个“掩码”位图是一个单色位图,它是位图图像的一个单色剪影。   在详细介绍实现过程之前先介绍下所使用的画图函数以及函数参数所代表的功能;整个绘制过程需要使用到BitBlt()函数。整个功能的实现过程如下:    (1) 创建一张大小与需要绘制图像相同的位图作为“掩码”位图;    (2) 将新创建的“掩码”位图存储至掩码位图的设备描述表;    (3) 把位图设备描述表的背景设置成“透明色”,不需要显示的颜色;    (4) 复制粘贴位图到“掩码”位图的设备描述表,这个时候“掩码”位图设备描述表存放的位图与位图设备描述表的位图一样;    (5) 把需要透明绘制的位图与对话框绘图相应区域的背景进行逻辑异或操作绘制到对话框上;    (6) 把“掩码”位图与这个时候对话框相应区域的背景进行逻辑与的操作;    (7) 重复步骤5的操作,把需要透明绘制的位图与对话框绘图相应区域的背景进行逻辑异或操作绘制到对话框上;    (8) 最后把系统的画笔还给系统,删除使用过的GDIObject,释放非空的指针,最后把新建的设备描述表也删除。 2.3 CObList链表 MFC类库提供了丰富的CObList类的成员函数,此程序主要用到的成员函数如下:(1) 构造函数,为CObject指针构造一个空的列表。 (2) GetHead(),访问链表首部,返回列表的首元素(列表不能为空)。(3) AddTail(),在列表尾增加一个元素或另一个列表的所有元素。   (4) RemoveAll(),删除列表所有的元素。   (5) GetNext(),返回列表尾元素的位置。   (6) GetHeadPosition(),返回列表首元素的位置。   (7) RemoveAt(),从列表删除指定位置的元素。   (8) GetCount(),返回列表的元素数。 在CPlaneGameView.h文件声明各游戏对象与游戏对象链表:   (1)//创建各游戏对象 CMyPlane *myplane; CEnemy *enemy; CBomb *bomb; CBall *ball; CExplosion *explosion; (2)//创建存储游戏对象的对象链表 CObList ListEnemy; CObList ListMe; CObList ListBomb; CObList ListBall; CObList ListExplosion; 2.4获取矩形区域   首先,使用CRect定义一个对象,然后使用GetClientRect(&对象名)函数,获取界面的矩形区域rect.Width() 为矩形区域的宽度,rect.Height()为矩形区域的高度。   使用IntersectRect(&,&))函数来判断两个源矩形是否有重合的部分。如果有不为空,则返回非零值;否则,返回0。 2.5使用AfxMessageBox显示游戏过程的提示信息   AfxMessageBox()是模态对话框,你不进行确认时程序是否往下运行时,它会阻塞你当前的线程,除非你程序是多线程的程序,否则只有等待模态对话框被确认。   在MFC,afxmessagebox是全局的对话框最安全,也最方便。 2.6内存释放   在VC/MFC用CDC绘图时,频繁的刷新,屏幕会出现闪烁的现象,CPU时间占用率相当高,绘图效率极低,很容易出现程序崩溃。及时的释放程序所占用的内存资源是非常重要的。   在程序使用到的链表、刷子等占用内存资源的对象都要及时的删除。Delete Brush, List.removeall()等。 2.7 CImageList处理爆炸效果   爆炸效果是连续的显示一系列的图片。如果把每一张图片都显示出来的话,占用的时间是非常多的,必然后导致程序的可行性下降。CImageList是一个“图象列表”是相同大小图象的集合,每个图象都可由其基于零的索引来参考。可以用来存放爆炸效果的一张图片,使用Draw()函数来绘制在某拖拉操作正被拖动的图象,即可连续绘制出多张图片做成的爆炸效果。 2.8对话框的应用    在设置游戏难度、炸弹的速度等,使用对话框进行设置非常方便,又体现出界面的友好。    对话框的应用过程如下:    (1). 资源视图下,添加Dialog对话框。然后添加使用到的控件,并修改控件的ID以便于后面的使用。    (2). 为对话框添加类,在对话框模式下,点击项目,添加类。    (3). 在类视图,为对话框类添加成员变量(控件变量)。设置变量的名称、类型、最值等信息。    (4). 在资源视图菜单,选择相应的菜单项,右击添加时间监听程序,设置函数处理程序名称。    (5). 在处理程序函数添加相应的信息。 3. 总体设计与详细设计 3.1 系统模块划分   该飞机大战游戏程序分为游戏背景位图绘制模块、各游戏对象绘制模块、游戏对象之间的碰撞模块、爆炸效果产生模块、游戏界面输出玩家得分关卡信息模块。   其在游戏对象绘制模块,战机是唯一对象,在游戏开始时产生该对象,赋予其固定的生命值,当其与敌机对象、敌机炸弹碰撞时使其生命值减一,直至生命值为零,便删除战机对象。敌机对象与敌机炸弹对象的绘制采用定时器技术,定时产生。爆炸对象初始化为空,当游戏过程即时发生碰撞时,在碰撞位置产生爆炸对象,添加到爆炸链表。 3.2 主要功能模块 3.2.1 系统对象类图            CGameObject是各个游戏对象的抽象父类,继承自CObject类,其他的类:战机类、敌机类、爆炸类、子弹类、炸弹类、文字类都继承了此类。   每个游戏对象类既继承了来自父类CGameObject的属性,又有自己的特有属性和方法。 3.2.2 系统主程序活动图    3.2.3 系统部分流程图 (1) 该飞机大战游戏执行流程图: (2) 利用定时器定时产生敌机并绘制敌机流程图 4. 编码实现 4.1 绘制游戏背景位图程序   CDC *pDC=GetDC();   //获得矩形区域对象   CRect rect;   GetClientRect(&rect;);   //设备环境对象类----CDC类。   CDC cdc;   //内存承载临时图像的位图   CBitmap bitmap1;   //该函数创建一个与指定设备兼容的内存设备上下文环境(DC)   cdc.CreateCompatibleDC(pDC);   //该函数创建与指定的设备环境相关的设备兼容的位图。   bitmap1.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());   //该函数选择一对象到指定的设备上下文环境,该新对象替换先前的相同类型的对象。   CBitmap *pOldBit=cdc.SelectObject(&bitmap1;);   //用固定的固体色填充文本矩形框   cdc.FillSolidRect(rect,RGB(51,255,255)); //添加背景图片   CBitmap bitmap_BackGround;   bitmap_BackGround.LoadBitmap(IDB_BACKGROUND);   BITMAP bimap2;//位图图像   bitmap_BackGround.GetBitmap(&bimap2;);   CDC cdc_BackGround;//定义一个兼容的DC   cdc_BackGround.CreateCompatibleDC(&cdc;);//创建DC   CBitmap*Old=cdc_BackGround.SelectObject(&bitmap;_BackGround);   cdc.StretchBlt(0,0,rect.Width(),rect.Height(),&cdc;_BackGround,0,0,bimap2.bmWidth,bimap2.bmHeight,SRCCOPY); 4.2 飞机大战游戏对象的绘制程序 //画战机对象(唯一) if(myplane!= NULL) { myplane->Draw(&cdc;,TRUE); } //设置定时器,随机添加敌机,敌机随机发射炸弹,此时敌机速度与数量和关卡有关 SetTimer(2,300,NULL);//敌机产生的定时器 SetTimer(3,500,NULL);//敌机炸弹产生的定时器   if(myplane!=NULL&& is_Pause == 0) { switch(nIDEvent) { case 2://设置定时器产生敌机 { if(pass_Num == 1)//第一关 { int motion =1;//设置敌机的方向,从上方飞出 CEnemy *enemy=new CEnemy(motion); ListEnemy.AddTail(enemy);//随机产生敌机 }//if else if(pass_Num >= 2)//第一关以后的关卡 { int motion1 = 1; //设置敌机的方向,从上方飞出 CEnemy *enemy1=new CEnemy(motion1); enemy1->SetSpeed_en((rand()%5 +1)* pass_Num); ListEnemy.AddTail(enemy1);//随机产生敌机 int motion2 = -1;//设置敌机的方向,从下方飞出 CEnemy *enemy2=new CEnemy(motion2); enemy2->SetSpeed_en((rand()%5 +1)* pass_Num); ListEnemy.AddTail(enemy2);//随机产生敌机 }//else if }//case break; }//switch //判断产生的敌机是否出界,若已经出界,则删除该敌机 POSITION posEn=NULL,posEn_t=NULL; posEn=ListEnemy.GetHeadPosition(); int motion = 1; while(posEn!=NULL) { posEn_t=posEn; CEnemy *enemy= (CEnemy *)ListEnemy.GetNext(posEn); //判断敌机是否出界 if(enemy->GetPoint().xGetPoint().x>rect.right ||enemy->GetPoint().yGetPoint().y>rect.bottom) { ListEnemy.RemoveAt(posEn_t); delete enemy; }//if else { enemy->Draw(&cdc;,TRUE); switch(nIDEvent) { case 3://设置定时器产生敌机炸弹 {   CBall*ball=newCBall(enemy->GetPoint().x+17,   enemy->GetPoint().y+30,enemy->GetMotion()); ListBall.AddTail(ball); }//case break; }//switch }//else }//while //判断产生的敌机炸弹是否出界,若已经出界,则删除该敌机炸弹 POSITION posball=NULL,posball_t=NULL; posball= ListBall.GetHeadPosition(); while(posball!=NULL) { posball_t=posball; ball= (CBall *) ListBall.GetNext(posball); if( ball->GetPoint().xGetPoint().x>rect.right || ball->GetPoint().yGetPoint().y>rect.bottom) { ListBall.RemoveAt(posball_t); delete ball; }//if else { ball->Draw(&cdc;,1); }//else }//while }//if 4.3 飞机大战游戏对象战机位置的动态控制 if(myplane!= NULL) { myplane->Draw(&cdc;,TRUE); } //获得键盘消息,战机位置响应,战机速度speed为30 if((GetKeyState(VK_UP) <0 || GetKeyState('W') GetPoint().ySetPoint( myplane->GetPoint().x,rect.bottom); else myplane->SetPoint(myplane->GetPoint().x,( myplane->GetPoint().y - speed) ); }//if if((GetKeyState(VK_DOWN) <0|| GetKeyState('S') < 0)&& is_Pause== 0)//下方向键{}//if if((GetKeyState(VK_LEFT) <0|| GetKeyState('A') < 0)&& is_Pause== 0)//左方向键{}//if if((GetKeyState(VK_RIGHT) <0|| GetKeyState('D') < 0)&& is_Pause== 0)//右方向键{}//if if((GetKeyState(VK_SPACE)GetPoint().x, myplane->GetPoint().y,1); ListBomb.AddTail(BombOne); CBomb*BombTwo=newCBomb(myplane->GetPoint().x+35, myplane->GetPoint().y,1); ListBomb.AddTail(BombTwo); PlaySound((LPCTSTR)IDR_WAVE2,AfxGetInstanceHandle(),SND_RESOURCE |SND_ASYNC); }//if if(GetKeyState('Z')SetPoint(point.x,point.y); } //鼠标控制战机,发射战机子弹 void CPlaneGameView::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 CView::OnLButtonDown(nFlags, point); if( is_Pause == 0) { CBomb *BombOne=new CBomb( myplane->GetPoint().x, myplane->GetPoint().y,1); PlaySound((LPCTSTR)IDR_WAVE2, AfxGetInstanceHandle(), SND_RESOURCE |SND_ASYNC); ListBomb.AddTail(BombOne); CBomb *BombTwo=new CBomb( myplane->GetPoint().x+35, myplane->GetPoint().y,1); ListBomb.AddTail(BombTwo); } } 4.4 飞机大战游戏对象之间的碰撞实现 本飞机大战游戏的碰撞考虑了飞机子弹打敌机、敌机炸弹打战机、战机与敌机相撞、敌机炸弹与战机子弹相撞四种情况,根据游戏对象的矩形区域是否有交叉,而确认两者是否相撞,而产生爆炸对象,添加到爆炸链表。以战机与敌机相撞为例: if(myplane != NULL&& is_Pause== 0) { POSITION enemyPos,enemyTemp; for(enemyPos= ListEnemy.GetHeadPosition();(enemyTemp=enemyPos)!=NULL;) { enemy =(CEnemy *) ListEnemy.GetNext(enemyPos); //获得敌机的矩形区域 CRect enemyRect = enemy->GetRect(); //获得战机的矩形区域 CRect myPlaneRect = myplane->GetRect(); //判断两个矩形区域是否有交接 CRect tempRect; if(tempRect.IntersectRect(&enemyRect;,myPlaneRect)) { CExplosion *explosion = new CExplosion( enemy->GetPoint().x+18 , enemy->GetPoint().y + 18); PlaySound((LPCTSTR)IDR_WAVE,AfxGetInstanceHandle(), SND_RESOURCE |SND_ASYNC); ListExplosion.AddTail(explosion); //战机生命值减一 lifeNum_Me--; //删除敌机 ListEnemy.RemoveAt(enemyTemp); delete enemy; if(lifeNum_Me == 0) { //删除战机对象 delete myplane; myplane=NULL; }//if break; }//if }//for }//if 战机子弹打敌机、敌机炸弹打战机以及战机子弹与敌机炸弹对象的碰撞实现同上。 4.5 游戏界面输出当前信息   if(myplane != NULL&& is_Pause== 0)    {    HFONT font;    font=CreateFont(20,10,0,0,0,0,0,0,0,0,0,100,10,0);    cdc.SelectObject(font);    CString str;    cdc.SetTextColor(RGB(255,0,0));    str.Format(_T("当前关卡:%d"),pass_Num);    cdc.TextOutW(10,20,str);    str.Format(_T("当前得分:%d"),score_Me);    cdc.TextOutW(10,40,str);    str.Format(_T("剩余生命:%d"),lifeNum_Me);    cdc.TextOutW(10,60,str);    }//if    if(myplane !=NULL && lifeNum_Me >0)    {    if(score_Me > 10*count_Life*pass_Num)    {    lifeNum_Me++;//生命值加1    count_Life++;//已增加生命值加1    }    } 游戏进入下一关,以及结束游戏界面设计代码与上类似。 5. 项目程序测试 5.1战机移动及子弹发射模块测试 用例 预期结果 实际结果 问题描述 修改方案 点击A键或鼠标左移 战机向左移动 战机向左移动 点击D键或鼠标右移 战机向右移动 战机向右移动 点击W键或鼠标上移 战机向上移动 战机向上移动 点击S键或鼠标上移 战机向下移动 战机向下移动 5.2敌机及炸弹模块测试 用例 预期结果 实际结果 问题描述 修改方案 玩家得分50(通过第一关后) 敌机从上下两方向均可飞出,且速度不断增加 敌机从上下两方向均可飞出,且速度不断增加 5.3爆炸模块测试 用例 预期结果 实际结果 问题描述 修改方案 战机子弹打敌机 敌机位置处爆炸,敌机消失,战机生命-1 敌机位置处爆炸,敌机消失,战机生命-1 敌机炸弹打战机 战机位置处爆炸,战机生命-1 战机位置处爆炸,战机生命-1 敌机战机相撞 敌机位置处爆炸,敌机消失,战机生命-1 敌机位置处爆炸,敌机消失,战机生命-1 战机子弹与敌机炸弹相撞 敌机炸弹处爆炸,子弹与炸弹均消失消失 敌机炸弹处爆炸,子弹与炸弹均消失消失 战机生命值==0 战机消失,GameOver或者过关 战机消失,GameOver或者过关 6. 实训遇到的主要问题及解决方法   (1)由于对C++的面向对象的思想和逻辑思路不熟悉,不明白其的封装之类的以及多态的思想,致使开始真正的进入实训接触到项目时没有开发思路,通过逐步查询书籍整理C++面向对象编程思路,才逐步理清项目的开发步骤。   (2)本飞机大战的游戏要求使用链表实现各游戏对象的存储和释放,由于链表知识掌握的不牢固,使用起来总是出现这样那样的错误,给整个游戏开发带来了很大的障碍,通过不断的调试修改,最终使程序正确运行。   (3)在绘制各种游戏对象—敌机和敌机炸弹时,开始使用随机函数,画出敌机时而很少,总是打不到预定的效果,后来经过修改使用定时器产生敌机和敌机炸弹,使整个游戏更加人性化。 7. 实训体会 (1)在本次飞机大战游戏项目的开发过程遇到很多问题,大部分是因为对MFC编程的不熟悉以及链表掌握不牢固所导致的。 (2)MFC编程有很多可以直接调用的函数,由于之前缺乏对这方面编程的经验,以至于本次项目开发过程走了很多弯路。 (3)通过寻求老师和同学的帮助,解决了开发遇到的很多问题,也提升了自己调试错误的能力。 (4)通过本次实训,使我熟悉了MFC编程技术、巩固了链表的使用方法并加深了对面向对象编程思想的理解,对以后程序的编写打下了良好的基础。
用变量a给出下面的定义 a) 一个整型数(An integer) b) 一个指向整型数的指针(A pointer to an integer) c) 一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to a pointer to an integer) 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 13.下面的数据声明都代表什么? (1)float (**def)[10]; def是一个二级指针,它指向的是一个一维数组的指针,数组的元素都是float. (2)double*(*gh)[10]; gh是一个指针,它指向一个一维数组,数组元素都是double*. (3)double(*f[10])(); f是一个数组,f有10个元素,元素都是函数的指针,指向的函数类型是没有参数且返回double的函数. (4)int *((*b)[10]); 就跟int *(*b)[10]是一样的,b是一维数组的指针. (5)Long (*fun)(int); 函数指针. (6)int (*(*F)(int,int))(int); F是一个函数指针,指向的函数的类型是有两个int参数并且返回一个函数指针的函数,返回的函数指针指向有一个int参数且返回int的函数.  所有的ASCII码都可以用“\”加数字(一般是8进制数字)来表示。而C定义了一些字母前加"\"来表示常见的那些不能显示的ASCII字符,如\0,\t,\n等,就称为转义字符,因为后面的字符,都不是它本来的ASCII字符意思了。   转义字符 意义 ASCII码值(十进制)   \a 响铃(BEL) 007   \b 退格(BS) 008   \f 换页(FF) 012   \n 换行(LF) 010   \r 回车(CR) 013   \t 水平制表(HT) 009   \v 垂直制表(VT) 011   \\ 反斜杠 092   \? 问号字符 063   \' 单引号字符 039   \" 双引号字符 034   \0 空字符(NULL) 000   \ddd 任意字符 三位八进制   \xhh 任意字符 二位十六进制   字符型常量   字符型常量所表示的值是字符型变量所能包含的值。我们可以用ASCII表达式来表示一个字符型常量,或者用单引号内加反斜杠表示转义字符。   'A', '\x2f', '\013';   其:\x表示后面的字符是十六进制数,\0表示后面的字符是八进制数。   注意:在Turbo C 2.0,字符型常量表示数的范围是-128到127,除非你把它声明为unsigned,这样就是0到255。   上面我们见到的\x,\n,\a等等都是叫转义字符,它告诉编译器需要用特殊的方式进行处理。下面给出所有的转义字符和所对应的意义:   转义字符 描述   \' 单引号   \ 双引号   \\ 反斜杠   \0 空字符   \ccc (最多三位)八进制数   \a 声音符   \b 退格符   \f 换页符   \n 换行符   \r 回车符   \t 水平制表符   \v 垂直制表符   \xhh(最多两位)十六进制符 下面的代码输出是什么,为什么? 1、sizeof()和strlen()的使用? 答: 1.从功能定义上,strlen函数,用来求字符串的长度,sizeof函数是用来求指定变量或变量类型等所占用内存的 大小; 2.sizeof是运算符,而strlen是C库函数strlen只能用char*做参数,且以'\0'结尾的; 对于静态数组处理: char str[20]="0123456789"; strlen(str)=10; //表示数组字符串的长度 sizeof(str)=20; //表示数组变量分配的长度 对于指针处理: char *str="0123456789"; strlen(str)=10; //表示字符串的长度 sizeof(str)=4; //表示指针变量的所占内存大小 sizeof(*str)=1; //表示'0'这个字符变量的所占内存大小 2、 struct 和 class的区别? 答: (1)类的成员默认是private的,当是可以声明为public,private 和protected,结构定义的成员默认的都是public. (2)结构不允许定义成员函数,当是类可以定义成员函数. (3)结构不可以存在继承关系,当是类可以存在继承关系. 3、 strcpy(), strcat(), strcmp,strlen(), strchr(), memcpy(), memcmp(), memset()的编写? 4、 内存的分配方式的分配方式有几种? 答: (1)从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量。 (2)在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集,效率很高,但是分配的内存容量有限。 (3)从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。 5,、解释堆和栈的区别? 答: (1)栈区(stack):由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构的栈。 (2)堆区(heap):一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构的堆是两回事,分配方式倒是类似于链表.(主要有:malloc/free,new/delete) 6,、枚举的用法,以及它与宏的区别? 答: 枚举(enum)作用:定义一组常量,而且这些常量组成了一个集合。当我们将emun参数传递给函数时,如果传递了一个不属于这个集合的参数,编译器报错。 区别: 枚举是类型,而宏没有类型。 枚举将检查其语法,而宏是简单的文本替换。 7、 const的用法,以及声明const变量与宏的区别? 答: const的用法有四种: a): const对象和const类型的对象; b): const指针 和 指向const的指针 及两者结合; c): const 参数修饰 和 参数返回类型的const修饰; d): const类成员 和 const 成员函数; 区别: const常量有数据类型, 而宏常量没有数据类型。编译器可以对前者进行类型安全检查,而对后者只能进行字符 替换,没有类型 安全检查。而且字符替换可能会带来料想不到的边界效应。有些集成化工具可以对const常量进行调试, 但不能对宏量进行调试。 8、函数assert的用法? 答:断言assert是仅在debug版本起作用的宏,用于检查“不应该“发生的情况。程序员可以把assert看成一个在任何系统状态下都可以安全使用的无害测试手段。 9、用预处理指令#define 声明一个常数,用以表明1年有多少秒(忽略闰年问题)? 答: #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 10、 写一个"标准"宏MIN,这个宏输入两个参数并返回较小的一个? 答: #define MIN(A,B) ((A) <= (B) ? (A) : (B)) 11、嵌入式系统经常要用到无限循环,你怎么样用C编写死循环呢? 答: 这个问题用几个解决方案。我首选的方案是: while(1) { } 一些程序员更喜欢如下方案: for(;;) { } 13、关于内存对齐的问题以及sizof()的输出? 答: 编译器自动对齐的原因:为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;然而,对齐的内存访问仅需要一次访问。 14、 static有什么用途?(请至少说明两种) 答: (1)在函数体,一个被声明为静态的变量在这一函数被调用过程维持其值不变。 (2) 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。 (3) 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。 15、引用与指针有什么区别? 答: (1) 引用必须被初始化,指针不必。 (2) 引用初始化以后不能被改变,指针可以改变所指的对象。 (3) 不存在指向空值的引用,但是存在指向空值的指针。 16、什么是平衡二叉树? 答: 左右子树都是平衡二叉树 且左右子树的深度差值的绝对值不大于1。 17、堆栈溢出一般是由什么原因导致的? 答: 没有回收垃圾资源。 18、什么是预编译?何时需要预编译? 答: (1)总是使用不经常改动的大型代码体。 (2)程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。在这种情况下,可以将所有包含文件预编译为一个预编译头。 19、队列和栈有什么区别? 答: 队列先进先出;栈后进先出。 20、数组和链表的区别? 答: 数组:数据顺序存储,固定大小; 链表:数据可以随机存储,大小可动态改变; 21、为什么数组名作为参数,会改变数组的内容,而其它类型如int却不会改变变量的值? 答: 当数组名作为参数时,传递的实际上是地址。而其他类型如int作为参数时,由于函数参数值实质上是实参的一份拷贝,被调函数内部对形参的改变并不影响实参的值。 22、数据结构和算法: A:查找: (1)二分法查找; B:写出下列算法的时间复杂度和实现排序: (1)冒泡排序; (2)选择排序; (3)插入排序; (4)快速排序; (5)堆排序; (6)归并排序; 23、编写gbk_strlen函数,计算含有汉字的字符串的长度,汉字作为一个字符处理;已知:汉字编码为双字节,其 参数里涉及指针,就要考虑该指针是不是一个需要修改的量,如果是,则参数应采用指向指针的指针。 (C语言里参数传递都是传值,是一个拷贝,修改指针,只是改变了拷贝的指向,原指针指向并没有改变,而修改指针的内容则是可以的。)如果函数的参数是一个指针,不要指望用该指针去申请动态内存。(即上面所说的修改该指针) 编译器总是要为函数的每个参数制作临时副本,指针参数p的副本是 _p,指针参数也不例外。 如果非得要用指针参数去申请内存,那么应该改用“指向指针的指针”,由于“指向指针的指针”这个概念不容易理解,我们也可以用函数返回值来传递动态内存。 常常有人把return语句用错了。这里强调不要用return语句返回指向“栈内存”的指针,因为该内存在函数结束时自动消亡。 c语言里,利用函数的返回值来表明它是否执行成功的做法最常见。 2.如果要在单链表删除或插入一个元素,就必须知道指向删除点或插入点前面那个元素的指针才行。 数组具有随机存取性(可以立即存取任一元素) char *str = "the word" 常量字符串,静态存储区,具有程序生命期。 char *str = (char *)malloc(....); 堆上分配,手动释放,否则内存泄漏。 char str[] = "the word" 栈上分配,函数生命期。 4. '\0'不是指ASCII码值,它是字符,它的ASCII码值是0,也就是ASCII码表的第一个字符。'\0'并非是空格空格的ASCII码值是32,只不过是输出类似于空格而已。 5. 在32位程序里,所有类型的指针的值都是一个32位整数,因为32位程序里内存地址全都是32位长,指针本身占据了4个字节的长度,即用一个字的空间保存一个地址。地址是按字节表示的,一个字节一个地址。地址+1,移动一个字节。 6.从语法上看,你只须把指针声明语句的指针名字和名字左边的指针声明符*去掉,剩下的就是指针所指向的类型。 *p的结果是p所指向的东西 &a的运算结果是一个指针,指针所指向的类型是a的类型,指针所指向的地址嘛,那就是a的地址。 7. 声明了一个数组TYPE array[n],则数组名称array就有了两重含义:第一,它代表整个数组,它的类型是TYPE[n];第二 ,它是一个指针,该指针的类型是TYPE*,该指针指向的内存区就是数组第0号单元,该指针自己占有单独的内存区. 在表达式sizeof(array),数组名array代表数组本身,故这时sizeof函数测出的是整个数组的大小。 sizeof(array+n)测出的是指针类型的大小。 char类型的长度是一个字节,int类型的长度是4个字节,即一个字。 sizeof()得到的值是以字节为单位,所以sizeof(int) = 4 8. char* 相当于string ,char* arr[10]即字符串数组

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值