传智播客C语言入门7_第1页
传智播客C语言入门7_第2页
传智播客C语言入门7_第3页
传智播客C语言入门7_第4页
传智播客C语言入门7_第5页
已阅读5页,还剩158页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

传智播客C语言入门教程(7)讲师:尹成QQ:77025077博客:/yincheng01微博:/yincheng8848Mail:yinc13@网址:C语言C++语言传智播客高薪就业2.链表讲解3.栈,队列,链表综合学习4.C语言实战5.C语言面试传智播客C语言入门教程(7)大纲1.编译及预处理C语言课程概述6.传智播客C/C++学院课程介绍7.1编译与预处理如果一个源程序由多个诸如A.c,B.h等的源文件组成,使用的编译链接器是如何根据这些文件生成可执行文件的?编译链接的机理到底是什么,这是本章要学习的内容。对C语言来说,除了掌握必要的语法机制外,学好预处理命令也是写出高质量代码的前提。7.1.1宏定义及编译预处理定义4宏宏替换\预处理预处理是指在进行编译之前所作的处理,由预处理程序负责完成

用一个标识符来表示一个字符串,称为“宏”,被定义为“宏”的标识符称为“宏名”。

在编译预处理时,对程序中所有出现的“宏名”,都用宏定义中的字符串去代换,这称为“宏代换”或“宏展开”;

7.1.2HelloWorld案例拓展很多示例代码,实际上,哪怕是像Hello,World这样简单的示例程序,都要经过编辑、预处理、编译、链接4个步骤,才能变成可执行程序,鼠标双击就弹出命令窗口,显示“Hello,World”。这也是一般C语言程序的编译流程,如所示。7.1.3编辑编辑可能就是通常所说的“写代码”,用集成开发工具也好,用记事本也好,按C语言的语法规则组织一系列的源文件,主要有两种形式,一种是.c文件,另一种是.h文件,也称头文件。7.1.4预处理前面接触到的“#include”和“#define”都属于编译预处理,C语言允许在程序中用预处理指令写一些命令行。预处理器在编译器之前根据指令更改程序文本。编译器看到的是预处理器修改过的代码文本,C语言的编译预处理功能主要包括宏定义、文件包含和条件编译3种。预处理器对宏进行替换,并将所包含的头文件整体插入源文件中,为后面要进行的编译做好准备。7.1.5编译编译器处理的对象是由单个c文件和其中递归包含的头文件组成的编译单元,一般来说,头文件是不直接参加编译的。编译器会将每个编译单元翻译成同名的二进制代码文件,在DOS和Windows环境下,二进制代码文件的后缀名为.obj,在Unix环境下,其后缀名为.o,此时,二进制代码文件是零散的,还不是可执行二进制文件。错误检查大多是在编译阶段进行的,编译器主要进行语法分析,词法分析,产生目标代码并进行代码优化等处理。为全局变量和静态变量等分配内存,并检查函数是否已定义,如没有定义,是否有函数声明。函数声明通知编译器:该函数在本文件晚些时候定义,或者是在其他文件中定义。7.1.6链接链接器将编译得到的零散的二进制代码文件组合成二进制可执行文件,主要完成下述两个工作,一是解析其他文件中函数引用或其他引用,二是解析库函数。举例来说,某个程序由两个c文件组成,分别为A.c、B.c,两个c文件和其中递归包含的头文件组成的两个编译单元,经过预处理和编译生成二进制代码文件A.obj和B.obj,假设A.c中调用了函数C,可函数C定义在B.c中,A.obj中实际上仅仅包括着对C函数的引用,其二进制定义代码需要从B.obj中提取,插入到A.obj的调用处,这个过程称为函数解析(resolve),由链接器完成。不仅仅是函数,变量(诸如有外部链接性的全局变量)也牵扯到解析的问题。当B.c没有定义函数C时,编译时不会产生错误,但链接时却会提示,有未解析的对象,据此可分析出问题出在编译阶段还是链接阶段。7.1.7程序错误兴致勃勃地写完程序,编译链接,一大堆的错误提示,不要沮丧,再优秀的程序员也会犯错,有人说,程序编写的过程大部分的时间都是用在错误调试上。有时为了排除一个小问题,可能会几天几夜地跟踪代码,正因为如此,有人把问题找到并解决的刹那称为“痛苦的幸福”。继续说明程序错误前,有个观点要说明:没有完美的程序,不存在没有缺陷的程序,如果一个程序运行很完美,那是因为它的缺陷到现在还没有被发现。同样,软件测试是为了发现程序中可能存在的问题,而不是证明程序没有错误。7.1.8错误分类错误可分两大类,一是程序书写形式在某些方面不合C语言要求,称为语法错误,这种错误将会由编译器指明,是种比较容易修改的错误,二是程序书写本身没错,编译链接能够完成,但输出结果与预期不符,或着执行着便崩溃掉,称为逻辑错误。细分下去,语法错误又可分为编译错误和链接错误,很明显,编译错误就是在程序编译阶段出的错误,而链接错误就是在程序链接阶段出的问题。7.1.9编译错误如果文件中出现编译错误,编译器将给出错误信息,并指明错误所在的行,提示用户修改代码,编译错误主要有两类:(1)语法问题,缺少符号,如缺分号,缺括号等,符号拼写不正确,一般来说,编译器都会指明错误所在行,但由于代码是彼此联系的,有时编译器给出的信息未必正确。一般来说,源程序中出错位置要么就是编译器提示位置,要么在提示位置之前,甚至是在前面很远的地方。另一个问题是有时一个实际错误会让编译器给出很多出错提示,所以,面对成百上千个错误提示时,不要害怕,没准修改一处代码,所有的问题都解决了。(2)上下文关系有误,程序设计中有很多彼此关联的东西,比如变量要先创建再使用,有时编译器会发现某个变量尚未定义,便会提示出错。这种情况有时是因为变量名拼写有误,有时是因为确实忘了定义。除了错误外,编译器还会对程序中一些不合理的用法进行警告(warning),尽管警告不耽误程序编译链接,但对警告信息不能掉以轻心,警告常常预示着隐藏很深的错误,特别是逻辑错误,应当仔细排查。7.1.10链接错误当一个编译单元中调用了库函数或定义在其他编译单元中的函数时,在链接阶段就需要从库文件或其他目标文件中抽取该函数的二进制代码,以便进行组合等一系列工作,找不到函数定义时,链接器无法找到该函数对应的代码,便会提示出错,指出名字未解析。一般来说,链接器给出的错误提示信息是关乎函数的链接。7.1.11逻辑错误即使程序顺利通过了编译链接,也不是说万事大吉,可以收工了,要检查生成的可执行程序,看其是否实现了所需的功能。实际上,运行阶段出现的逻辑错误更难排查,更让人头疼,编译错误和链接错误好歹有提示信息,但面对逻辑错误,就像浑水摸鱼。可能出现的逻辑错误有以下情况:与操作系统有关的操作,是否进行了非法操作,如非法内存访问等。是否出现了死循环,表现为长时间无反应,假死,注意,长时间无反应并不一定都是死循环,有的程序确实需要很长时间,这种情况要仔细分析。程序执行期间发生了一些异常,比如除数为0等,操作无法继续进行。程序能正确执行,但结果不对,此时应检查代码的编写是否合乎问题规范。7.1.12排错排除错误,有两层含义,找到出错的代码,修改该代码。排错也有两种形式,一是静态排错,编译器和链接器发现的错误基本都属于这一类,通过观察源程序便能确定问题所在并改正它。另一种是动态排错,逻辑错误的发现和纠正都比较困难,要综合考虑代码、使用的数据和输出结果的关联,仔细思考,尝试更换数据,观察结果的改变,依此分析错误可能存在的地方。如果还是不行,就要使用动态检查机制,最基本的方法是“分而治之”,检查程序执行的中间状态,最常用的方法是在可能出错的地方插入一些输出语句,让程序输出一些中间变量的值,确定可能出错的区域。此外,还可利用编译环境提供的DEBUG工具,对程序进行跟踪、监视和设断点等,定位并排错。7.1.13预处理命令预处理命令的引入是为了优化程序设计环境,提高编程效率,合理使用预处理命令能使编写的程序易于阅读、修改、移植和调试,也有利于程序的模块化设计。预处理命令必须独占一行,并以#开头,末尾不加分号,以示与普通C语句的区别。原则上,预处理行可以写在程序的任何位置,但推荐(或是惯常写法)写在程序文件的头部。编译器在对文件进行实质性的编译之前,先处理这些预处理行,这也是“预”字的含义。C语言的编译预处理功能主要包括宏定义、文件包含和条件编译3种。7.1.14宏定义对宏已经不再陌生,在字符常量一节中,已经介绍过#define的用法,宏即是用#define语句定义的。宏定义是用宏名来表示一个字符串,在编译预处理时,对程序中所有出现的宏名,都用宏定义中的字符串来替换,称为“宏代换”或“宏展开”。宏展开只是种简单的代换,字符串中可以包含任何字符,可以是常数,也可以是表达式,预处理器进行宏展开时并不进行语法检查。7.1.15不带参的宏定义不带参数宏的一般定义形式为:#define宏名宏体宏名的命名规则与变量相同,一般习惯用大写字母,以便与变量区分,当然,这并不是说不允许使用小写字母作为宏名。来看一个不带参数宏的示例,从中学习一些宏的用法:#include<stdio.h> /*使用printf要包含的头文件*/#include<stdlib.h>#defineSIDE5#defineSQUARESIDE*SIDE /*宏定义允许嵌套*/#definePI3.14159265#defineOUTPUTprintf("Hello,C\n");voidmain(void) /*主函数*/{ intx=SQUARE; printf("xis%d\n",x); if(PI<4) OUTPUT printf("PIis%f",PI); getcharar(); /*等待,按任意键继续*/}7.1.16#define定义常量与宏常量#define定义的常量称为符号常量,而const常量常称静态常量,相比#define,const有很多优势,在实际使用时,推荐采用const定义常量。对#define定义的符号常量,预处理器只是进行简单的字符串替换,并不对其进行类型检查,而且会与程序中定义的同名变量冲突,如:#definenum10;voiddisp(){intnum;Printf(“%d”,num);}编译时,预处理器会将disp函数中的语句“intnum;”替换成“int10”,若使用“constintnum=10;”便不会出现这种问题。7.1.17宏定义的规则1、预处理程序对宏定义不作语法检查。2.宏定义不是普通C语句,在行末不必加分号,如加上分号则连分号也一起置换例#defineN3Omain(){inti;for(i=1;i<=N;i++) printf("%d\n",i);}7.1.18宏定义的规则宏名在源程序中若用引号括起来,则预处理程序不对其作置换例#definePRICE88main(){printf("PRICEIS%d",PRICE);}

运行结果如下:PRICEIS88而不是88IS88,即双引号中的PRICE没有用88代替

同一个宏名不能重复定义

如#definePRICE88和#definePRICE100不能同时出现在同一段程序中。

7.1.19宏定义的规则宏定义中的字符串不能替换用户标志符中与宏名相同的部分

#definePRICE88main(){intBOOK_PTICE=10;}程序中的BOOK_PTICE中的PRICE不会被替换为BOOK_88。7.1.20宏定义的规则

宏定义允许嵌套,在宏定义的字符串中可以使用已经定义的宏名。在宏展开时由预处理程序层层代换。

#defineM10#defineN2#defineXM+100#defineYM*Nmain(){printf("M=%d\nN=%d\nX=%d\nY=%d\n",M,N,X,Y);}运行结果是:M=10N=2X=110Y=20在第三条宏定义#defineXM+100语句中,用到了前面已经定义过的宏M7.1.21宏定义的规则宏定义一般写在函数之外,其作用域为宏定义命令起到源程序结束。如要终止其作用域可使用#undef命令。#defineN100main(){

……}#undefNmax(){

……}N只在main函数中有效,在max中无效

7.1.22带参数的宏定义C语言有一类宏可以带有参数,在宏定义中的参数称为形式参数,在宏展开中的参数称为实际参数。

带参数的宏在编译连接后,不仅要展开宏,而且要用实参去代换形参,在宏定义中的形参是标识符,而宏展开中的实参可以是任意表达式。带参宏定义的一般形式为:#define宏名(形参表)字符串带参宏展开的一般形式为:

宏名(实参表);

例:

#defineADD(x)x*10/*宏定义*/

……

a=ADD(3);/*宏展开*/在宏展开时,用实参3去代替形参x,经预处理宏展开后的语句为:

a=3*10;7.1.23带参的宏定义#defineCUBE(x)((x)*(x)*(x))main(){doubley;floatz=10;inti;intj=2;y=CUBE(z);i=CUBE(j);printf("y=%8.1f\ni=%d\n",y,i);}运行结果是:y=1000.0i=8执行语句y=CUBE(z);时自动将z的值代替((x)*(x)*(x))中的x,执行语句i=CUBE(j);时自动将j的值代替((x)*(x)*(x))中的x,并且将结果返回给CUBE,再分别赋值给y、i

7.1.24带参的宏定义

类似函数的带参数宏定义#include"stdio.h"#defineexchange(a,b){intt; t=a;a=b;b=t;}voidmain(){ intx=10; inty=20; printf("x=%d;y=%d\n",x,y); exchange(x,y); printf("afterexchange:x=%d;y=%d\n",x,y);}上述程序运行结果如下:x=10;y=20afterexchange:x=20;y=107.1.25文件包含文件包含是C语言预处理的另一个重要功能,用“#include”来实现,将一个源文件的全部内容包含到另一个源文件中,成为它的一个部分,文件包含的一般格式为:#include<文件名>或者#include“文件名”两种形式的区别在于:使用尖括号表示在系统头文件目录中查找(由用户在设置编程环境时设置),而不在源文件目录中查找。使用双引号则表示首先在当前的源文件目录中查找,找不到再到系统头文件目录中查找。#include“文件名”格式下,用户可以显式指明文件的位置,如:#include“D:\A\B\C.h”#include“..\X.h” /*上级目录下的X.h文件*/#include“.\X.h”

/*当前级目录下的X.h文件*/#include“\X.h” /*当顶级目录下的X.h文件*/7.1.26文件包含1、一条include命令只能指定一个被包含文件,若有多个文件要包含,则需用多个include命令。不能这样写include语句:#include“m1.h,m2.h”

或#include“m1.h”,”m2.h”而必须写成:#include“m1.h”#include“m2.h”2、文件包含允许嵌套,即在一个被包含的文件中又可以包含另一个文件。3、文件包含语句中被包含的文件通常是以.h结尾的头文件,这种头文件中的内容多为变量的定义、类型定义、宏定义、函数的定义或说明,但被包含的文件也可以是以.c为扩展名的C语言源文件。7.1.27条件编译通过某些条件,控制源程序中的某段源代码是否参加编译,这就是条件编译的功能,一般来说,所有源文件中的代码都应参加编译,但有时候希望某部分代码不参加编译,应用条件编译可达到这以目的。条件编译的基本形式为:#if判断表达式

语句段1#else

语句段2#endif#ifndef标识符

程序段1

#else

程序段2

#endif

与第一种形式的区别是将“ifdef”改为“ifndef”。它的功能是,如果标识符未被#define命令定义过则对程序段1进行编译,

否则对程序段2进行编译。这与第一种形式的功能正相反。

7.1.28编译及预处理小节讨论了C语言程序编译及预处理的相关内容,C程序的编译分编辑、预处理、编译和链接几个步骤,预处理指令是由预处理器负责执行的,主要有头文件包含、宏定义、条件编译等,经过预处理后,编译器才开始工作,将每个编译单元编译成二进制代码文件,但此时分散的二进制代码文件中的变量和函数没有分配到具体内存地址,因而不能执行,需要链接器将这些二进制代码文件、用到的库文件中相关代码,系统相关的信息组合起来,形成二进制可执行文件。掌握程序编译链接的过程能帮助理解错误的根源,提高调试的效率,是写出高质量代码的必要条件。实现宏定义加减乘除函数,实现循环宏定义输出字符串传智播客,变量层叠宏定义1234条件编译实现中文英文韩文日文多语种界面实现将C语言的语句汉化,类型汉化,以及代码混淆实现条件编译,实现中英文界面7.1.29编译与预处理习题7.2.1C语言链表什么是链表链表是一种常见的重要的数据结构它是动态地进行存储分配的一种结构head12491249A135613561475B1475C10211021D\0头指针各结点地址不连续各结点含有两个部分表尾7.2.2C语言实现简单链表structStudent{intnum;

floatscore;

structStudent*next;}a,b,c;1010189.510103901010785a结点b结点c结点a.next=&b;b.next=&c;numscorenext7.2.3C语言实现简单链表建立简单的静态链表

建立一个如图所示的简单链表,它由3个学生数据的结点组成,要求输出各结点中的数据。1010189.510103901010785a结点b结点c结点numscorenext7.2.4C语言实现简单链表

建立简单的静态链表解题思路:1010189.510103901010785a结点b结点c结点numscorenextheadhead=&a;a.next=&b;b.next=&c;NULLc.next=NULL;7.2.5C语言实现动态链表所谓建立动态链表是指在程序执行过程中从无到有地建立起一个链表,即一个一个地开辟结点和输入各结点数据,并建立起前后相链的关系。写一函数建立一个有3名学生数据的单向动态链表。7.2.6创建链表过程链表的建立一般是指先建立一个空链表,而后一个个地将元素插在队尾。7.2.7表的插入顾名思义,插入即是往链表中加入一个新结点,使链表变长。受链表插入位置的影响,将一个元素插入链表有表头,表尾,表中:7.2.8链表删除节点删除几乎可以看成是结点插入的逆操作,将到换一个顺序即可:如果删除的是第1个数据结点,即从到,则应使head指针指向E1,同时释放掉Einsert申请的动态内存。如果删除的是中间结点,即从到,则只需让E2->next指向Einsert->next,同时,释放掉Einsert占据的动态内存。如果删除的尾结点,即从到,只需让E1->next为NULL,同时释放掉Einsert占据的动态内存。7.2.9链表逆置所谓链表的逆置,是指“头变尾,尾变头”,将原来的“ABCD……”变成“……DCBA”,先从单链表模型来看,如:7.2.10链表销毁在链表使用完毕后,需将其销毁,回收所分配的内存。由于是整体销毁,实现起来比结点的删除简单,可以采取如下策略:每次删除第1个结点后面的结点,最后再删除头结点,这样即可实现整个链表的销毁。仅仅删除第1个结点并不意味着整个链表被删除掉了,链表是一个结点一个结点建立起来的,所以,销毁它也必须一个结点一个结点地删除才行。编写链表销毁的函数如下:voidfreeAll(STU*head){STU*p=NULL,*q=NULL;p=head;while(p->next!=NULL){q=p->next;p->next=q->next; /*删除结点*/free(q); /*释放内存*/}free(head); /*释放第1个结点所占内存*/}7.2.11链表与数组的比较数组链表链表与数组的比较.内存中按照顺序存放寻址容易大小固定删除时需要很多移动静态数组无法增加,动态数组需要很多移动内存中按照指针链式存放寻址需要循环大小可变查找时需要很多移动删除,插入非常便捷啥时候用数组,啥时候用链表.各个不同实现链表逆转实现链表排序以及删除所有节点构建一个链表的数据结构7.2.12作业练习7.3栈,队列,综合学习栈和队列。栈和队列的操作受到了一定程度的限制对栈而言,只能在栈顶一端进行元素的插入和删除.队列只允许在一段插入,在另外一端删除元素。数据结构是合理组织数据的手段,掌握数据结构,能使代码组织清晰,程序质量高,易读易维护。7.3.1栈栈是种“先入后出”的结构,打个比方,栈相当于放餐具的带底木桶,而数据相当于一个个的盘子,刷完的盘子一个个摞起来放在桶里,用盘子时就一个个从桶中取出。很容易理解,最先刷好的盘子会放在桶底,此时,只有上面的盘子用光了才会将其拿出来,这就是所谓的先入后出FILO(FirstInLastOut),等价的说法是后入先出。一个栈有以下要素:栈底(表示栈的开始位置,木桶的底部),栈顶(当前数据已经排放在什么位置了,当前盘子摞了多高了),不含元素的栈称为空栈。形象的示意如:7.3.2顺序栈与链式栈根据元素储存方式的不同,可以将栈分为顺序栈和链式栈两类:(1)顺序栈利用一组连续的内存单元依次存放自栈底到栈顶的数据,同时,用一个指针top只是栈顶的位置,在C语言中,这可用数组来实现,一般是先开辟一块区域,在编程中可根据需要再对此区域进行调整。(2)链式栈链式栈的结构与链表类似,如所示,其中,top为栈顶指针,始终指向栈顶元素,栈顶元素的指针指向下一个元素,依此类推,直到栈底,栈底元素的指针区域为空如果top为空,表示该栈是个空栈。7.3.3栈的操作对栈元素的操作有一定限制,不允许随意访问栈中间的元素,只允许访问栈顶元素,对栈的操作有以下几种:判断栈是否为空,判断栈是否已满(只针对顺序栈),将一个元素压入栈,从栈中弹出一个元素,销毁一个栈(或称清空一个栈)。判断栈是否为空相对来说比较简单,只要判断下top指针是否为NULL即可,下面给出栈的使用范例,如:7.3.4队列日常生活中,去银行取款、火车站买票等都需要排队,队列这个名词大家一定不会陌生,和栈不同,队列的特点是“先到先办”FIFO(FirstInFirstOut),可将队列形象地比作管道,如所示:用栈实现进制转换用栈实现逆序用栈实现进制转换7.3.5作业练习项目实践算法

信息处理

游戏

安全案例实践案例实践案例实践案例实践7.4C语言实战自顶向下,逐步求精问题所在问题分析问题分解设计逻辑与封装逐步实现123457.4.1C语言设计规则7.4.2面向过程的编程方法

入口出口面向过程的编程方法传入数据传出结果对单个模块而言,只有一个入口,一个出口,是一种从上到下的流程式方法,减少了模块的相互联系使模块可作为插件或积木使用,降低程序的复杂性,提高可靠性面向过程编写高质量的C程序

设计规则设计理念封装可复用7.4.3C语言设计规则耦合度,是指模块之间相互依赖性大小的度量,耦合度越小,模块的相对独立性越大。内聚度,是指模块内各成份之间相互依赖性大小的度量,内聚度越大,模块各成份之间联系越紧密,其功能越强。AmericaEuropeAsia巴西美国非洲俄罗斯澳大利亚内聚耦合7.4.4实现高内聚与低耦合7.5经典C语言基本笔试题检验你前面学习的效果好坏,就看你是否能够通过世界五百强严酷的C语言考核,不过五百强很有挑战,你先搞定基础的面试题100题。面试笔试机试检验你是否通关100条经典C语言笔试题目1、请填写bool,float,指针变量与“零值”比较的if语句。提示:这里“零值”可以是0,0.0,FALSE或者“空指针”。例如int变量n与“零值”比较的if语句为:

if(n==0)if(n!=0)以此类推。100条经典C语言笔试题目(1)请写出boolflag与“零值”比较的if语句:【标准答案】if(flag)if(!flag)100条经典C语言笔试题目(2)请写出floatx与“零值”比较的if语句:【标准答案】constfloatEPSINON=0.00001;if((x>=-EPSINON)&&(x<=EPSINON)不可将浮点变量用“==”或“!=”与数字比较,应该设法转化成“>=”或“<=”此类形式。

100条经典C语言笔试题目(3)请写出char*p与“零值”比较的if语句【标准答案】if(p==NULL)if(p!=NULL)

100条经典C语言笔试题目2、以下为Linux下的32位C程序,请计算sizeof的值。charstr[]=“Hello”;char*p=str;intn=10;请计算

(1)sizeof(str)=

(2)sizeof(p)=

(3)sizeof(n)=【标准答案】(1)6、(2)4、(3)4100条经典C语言笔试题目(4)voidFunc(charstr[100]){ ……;}请计算sizeof(str)=(5)void*p=malloc(100);请计算sizeof(p)=【标准答案】(4)4、(5)4100条经典C语言笔试题目3、

longa=0x801010;

a+5=?【标准答案】0x801010用二进制表示为:“100000000001000000010000”,十进制的值为8392720,再加上5就是8392725。100条经典C语言笔试题目4、写一个函数找出一个整数数组中,第二大的数。

100条经典C语言笔试题目5、设有以下说明和定义:

typedefunion{longi;intk[5];charc;}DATE;

structdata{intcat;DATEcow;doubledog;}too;

DATEmax;

则语句

printf("%d",sizeof(structdate)+sizeof(max));的执行结果是:_____【标准答案】DATE是一个union,变量公用空间.里面最大的变量类型是int[5],占用20个字节.所以它的大小是20

data是一个struct,每个变量分开占用空间.依次为int4+DATE20+double8=32.

所以结果是

20+32=52.

100条经典C语言笔试题目6、请问以下代码有什么问题:

intmain()

{

chara;

char*str=&a;

strcpy(str,"hello");

printf(str);

return0;

}【标准答案】没有为str分配内存空间,将会发生异常

问题出在将一个字符串复制进一个字符变量指针所指地址。虽然可以正确输出结果,但因为越界进行内在读写而导致程序崩溃。100条经典C语言笔试题目7、请问以下代码有什么问题:char*s="AAA";

printf("%s",s);

s[0]='B';

printf("%s",s);

有什么错?【标准答案】"AAA"是字符串常量。s是指针,指向这个字符串常量,所以声明s的时候就有问题。

cosntchar*s="AAA";

然后又因为是常量,所以对是s[0]的赋值操作是不合法的。100条经典C语言笔试题目8、

写出下面的结果charstr1[]="abc";charstr2[]="abc";constcharstr3[]="abc";constcharstr4[]="abc";constchar*str5="abc";constchar*str6="abc";char*str7="abc";

char*str8="abc";cout<<(str1==str2)<<endl;cout<<(str3==str4)<<endl;cout<<(str5==str6)<<endl;cout<<(str7==str8)<<endl;

100条经典C语言笔试题目9、

c和c++中的struct有什么不同?【标准答案】c和c++中struct的主要区别是c中的struct不可以含有成员函数,而c++中的struct可以。100条经典C语言笔试题目10、

写出输出结果Intmain(){inta[5]={1,2,3,4,5};int*ptr=(int*)(&a+1);printf("%d,%d",*(a+1),*(ptr-1));}

100条经典C语言笔试题目11、

charszstr[10];

strcpy(szstr,"0123456789");

产生什么结果?为什么?【标准答案】长度不一样,出现段错误。100条经典C语言笔试题目12、

inta=248;b=4;intconstc=21;constint*d=&a;int*conste=&b;intconst*fconst=&a;请问下列表达式哪些会被编译器禁止?为什么?100条经典C语言笔试题目13、

voidmain()

{

charaa[10];

printf(“%d”,strlen(aa));

}会出现什么问题?打印结果是是多少?【标准答案】sizeof()和初不初始化,没有关系,strlen()和初始化有关,打印结果值未知。100条经典C语言笔试题目14、给定结构structA

{

chart:4;

chark:4;

unsignedshorti:8;

unsignedlongm;

};问sizeof(A)=?【标准答案】8100条经典C语言笔试题目15、

structname1{

charstr;

shortx;

intnum;

};求sizeof(name1)? 【标准答案】8100条经典C语言笔试题目16、

structname2{

charstr;

intnum;

shortx;

};求sizeof(name2)? 【标准答案】12100条经典C语言笔试题目17、程序哪里有错误wap(int*p1,int*p2){int*p;*p=*p1;*p1=*p2;*p2=*p;}【标准答案】p为野指针100条经典C语言笔试题目18、什么是预编译,何时需要预编译?

预编译又称为预处理,是做些代码文本的替换工作。处理#开头的指令,比如拷贝#include包含的文件代码,#define宏定义的替换,条件编译等,就是为编译做的预备工作的阶段,主要处理#开始的预编译指令,预编译指令指示了在程序正式编译前就由编译器进行的操作,可以放在程序中的任何位置。c编译系统在对程序进行通常的编译之前,先进行预处理。c提供的预处理功能主要有以下三种:1)宏定义2)文件包含3)条件编译100条经典C语言笔试题目19、

(void*)ptr和

(*(void**))ptr的结果是否相同?其中ptr为同一个指针。【标准答案】(void*)ptr和

(*(void**))ptr值是相同的100条经典C语言笔试题目20、要对绝对地址0x100000赋值,我们可以用

(unsignedint*)0x100000=1234;

那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做?【标准答案】*((void(*)())0x100000)();

首先要将0x100000强制转换成函数指针,即:

(void(*)())0x100000

然后再调用它:

*((void(*)())0x100000)();100条经典C语言笔试题目21、

inta,b,c请写函数实现c=a+b,不可以改变数据类型,如将c改为longint,关键是如何处理溢出问题

【标准答案】booladd(inta,intb,int*c)

{

*c=a+b;

return(a>0&&b>0&&(*c<a||*c<b)||(a<0&&b<0&&(*c>a||*c>b)));

}100条经典C语言笔试题目22、关于内存的思考题(1)你能看出有什么问题?100条经典C语言笔试题目23、关于内存的思考题(2)你能看出有什么问题?100条经典C语言笔试题目25、关于内存的思考题(3)你能看出有什么问题?100条经典C语言笔试题目26、关于内存的思考题(4)你能看出有什么问题?100条经典C语言笔试题目27.main函数既然不会被其它函数调用,为什么要返回1

intmain(){intx=3;printf("%d",x);

return1;}100条经典C语言笔试题目28、请写出输出结果intsum(inta){autointc=0;staticintb=3;

c+=1;b+=2;return(a+b+c);}voidmain(){intI;inta=2;for(I=0;I<5;I++){printf("%d,",sum(a));}}

100条经典C语言笔试题目29、头文件中的ifndef/define/endif干什么用?【标准答案】防止该头文件被重复引用。100条经典C语言笔试题目30、#include<filename.h>和#include“filename.h”有什么区别?【标准答案】对于#include<filename.h>,编译器从标准库路径开始搜索filename.h;对于#include“filename.h”,编译器从用户的工作路径开始搜索filename.h。100条经典C语言笔试题目31、const有什么用途?(请至少说明两种)(1)可以定义const常量(2)const可以修饰函数的参数、返回值,甚至函数的定义体。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。100条经典C语言笔试题目32、

static有什么用途?(请至少说明两种)【标准答案】1.限制变量的作用域(static全局变量);

2.设置变量的存储域(static局部变量)。100条经典C语言笔试题目33、栈溢出一般是由什么原因导致的?【标准答案】使用内存超过了栈的大小。

100条经典C语言笔试题目34、如何引用一个已经定义过的全局变量?【标准答案】可以用引用头文件的方式,也可以用extern关键字,如果用引用头文件方式来引用某个在头文件中声明的全局变理,假定你将那个变量写错了,那么在编译期间会报错,如果你用extern方式引用时,假定你犯了同样的错误,那么在编译期间不会报错,而在连接期间报错。

100条经典C语言笔试题目35、全局变量可不可以定义在可被多个.C文件包含的头文件中?为什么?【标准答案】可以,在不同的C文件中以static形式来声明同名全局变量。可以在不同的C文件中声明同名的全局变量,前提是其中只能有一个C文件中对此变量赋初值,此时连接不会出错。

100条经典C语言笔试题目36、队列和栈有什么区别?【标准答案】队列先进先出,栈后进先出。100条经典C语言笔试题目37、完成输出下列字符**.*.*..*..*..*...*...*...*...*....*....*....*....*....*.....*.....*.....*.....*.....*.....*......*......*......*......*......*......*......

100条经典C语言笔试题目38、用宏定义写出swap(x,y),即交换两数。【标准答案】#defineswap(x,y)(x)=(x)+(y);(y)=(x)–(y);(x)=(x)–(y);

100条经典C语言笔试题目39、写一个“标准”宏,这个宏输入两个参数并返回较小的一个。【标准答案】#defineMin(X,Y)((X)>(Y)?(Y):(X))//结尾没有;

100条经典C语言笔试题目40、带参宏与带参函数的区别(至少说出5点)?【标准答案】带参宏带参函数处理时间编译时运行时参数类型无需定义程序长度变长不变占用存储空间否是运行时间不占运行时间调用和返回时占100条经典C语言笔试题目41、请写出数组的冒泡排序法,选择排序法,插入排序法。100条经典C语言笔试题目42、请写出链表的插入排序法,冒泡排序法。100条经典C语言笔试题目43、已知一个数组table,用一个宏定义,求出数据的元素个数。【标准答案】#defineNTBL(table)(sizeof(table)/sizeof(table[0]))100条经典C语言笔试题目44、

A.c和B.c两个c文件中使用了两个相同名字的static变量,编译的时候会不会有问题?这两个static变量会保存到哪里(栈还是堆或者其他的)?【标准答案】static的全局变量,表明这个变量仅在本模块中有意义,不会影响其他模块。

他们都放在静态数据区,但是编译器对他们的命名是不同的。

如果要使变量在其他模块也有意义的话,需要使用extern关键字。100条经典C语言笔试题目45、单连表的建立,把'a'--'z'26个字母插入到连表中,并且倒叙,还要打印100条经典C语言笔试题目46、求组合数:求n个数(1....n)中k个数的组合....

如:combination(5,3)

要求输出:543,542,541,532,531,521,432,431,421,321,100条经典C语言笔试题目47、求全排列:求n个数(1....n)中k个数的排列....

如:P(2,2)1221如:P(3,2)122113312332

100条经典C语言笔试题目48、程序的局部变量存在于___中,全局变量存在于____中,动态申请数据存在于___中。

【标准答案】程序的局部变量存在于栈(stack)中,全局变量存在于静态数据区中,动态申请数据存在于堆(heap)中。100条经典C语言笔试题目49、什么是预编译,何时需要预编译:【标准答案】1、总是使用不经常改动的大型代码体。

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

100条经典C语言笔试题目50、用两个栈实现一个队列的功能?要求给出算法和思路!【参考答案】设2个栈为A,B,一开始均为空.

入队:

将新元素push入栈A;

出队:

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

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

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

100条经典C语言笔试题目51、对于一个频繁使用的短小函数,在C语言中应用什么实现,在C++中应用什么实现?【标准答案】c用宏定义,c++用inline100条经典C语言笔试题目52、

1.用预处理指令#define声明一个常数,用以表明1年中有多少秒(忽略闰年问题)【参考答案】#defineSECONDS_PER_YEAR(60*60*24*365)UL

100条经典C语言笔试题目53、有一分数序列:1/2,1/4,1/6,1/8„„,用函数递归调用的方法,求此数列前20项的和

100条经典C语言笔试题目54、在C++程序中调用被C编译器编译后的函数,为什么要加extern“C”?【标准答案】C++语言支持函数重载,C语言不支持函数重载。函数被C++编译后在库中的名字与C语言的不同。假设某个函数的原型为:voidfoo(intx,inty);该函数被C编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。C++提供了C连接交换指定符号extern“C”来解决名字匹配问题。100条经典C语言笔试题目55、请简述以下两个for循环的优缺点。100条经典C语言笔试题目

100条经典C语言笔试题目56、两个字符串,s,t;把t字符串插入到s字符串中,s字符串有足够的空间存放t字符串100条经典C语言笔试题目57、请编写一个C函数,该函数在给定的内存区域搜索给定的字符,并返回该字符所在位置索引值。

100条经典C语言笔试题目58、请写出下列代码的输出内容

#include<stdio.h>

intmain()

{

inta,b,c,d;

a=10;

b=a++;

c=++a;

d=10*a++;

printf("b,c,d:%d,%d,%d",b,c,d);

return0;

}【标准答案】10,12,120

100条经典C语言笔试题目59、

unsignedchar*p1;

unsignedlong*p2;

p1=(unsignedchar*)0x801000;

p2=(unsignedlong*)0x810000;

请问p1+5=;

p2+5=;【标准答案】0x801005、0x810020

100条经典C语言笔试题目60、

main()

{

inta[5]={1,2,3,4,5};

int*ptr=(int*)(&a+1);

printf(“%d,%d”,*(a+1),*(ptr-1));

}

请问输出:【标准答案】2,5

100条经典C语言笔试题目61、请问下面程序有什么错误?

inta[60][250][1000],i,j,k;

for(k=0;k<=1000;k++)

for(j=0;j<250;j++)

for(i=0;i<60;i++)

a[i][j][k]=0;【标准答案】把循环语句内外换一下。100条经典C语言笔试题目62、以下是求一个数的平方的程序,请找出错误:

#defineSQUARE(a)((a)*(a))

inta=5;

intb;

b=SQUARE(a++);【标准答案】宏在预编译时会以替换的形式展开,仅仅会替换。涉及到宏的地方,不要用++

--,标准中对此没有规定,因此最终结果将会依赖于不同的编译器。执行程序的答案可能是25、也有可能是36。100条经典C语言笔试题目63、#defineMax_CB500

voidLmiQueryCSmd(StructMSgCB*pmsg)

{

unsignedcharucCmdNum;

......

for(ucCmdNum=0;ucCmdNum<Max_CB;ucCmdNum++)

{

......;

}}这段代码执行有什么问题?【标准答案】死循环unsignedchar//无符号字符型表示范围0~255

char//有符号字符型表示范围-128~127

100条经典C语言笔试题目64、请写入一个宏,传入变量的时候,输出变量名。100条经典C语言笔试题目65、程序输出结果是?【标准答案】8,10,12,14,16100条经典C语言笔试题目66、求输出【标准答案】16100条经典C语言笔试题目67、

intmodifyvalue(){ return(x+=10); } intchangevalue(intx) { return(x+=1); } voidmain() { intx=10; x++; changevalue(x); x++; modifyvalue(); printf("Firstoutput:%dn",x); x++; changevalue(x); printf("Secondoutput:%dn",x); modifyvalue(); printf("Thirdoutput:%dn",x); }输出?【标准答案】12、13、13100条经典C语言笔试题目68、有双向循环链表结点定义为:

structnode

{intdata;

structnode*front,*next;

};

有两个双向循环链表A,B,知道其头指针为:pHeadA,pHeadB,请写一函数将两链表中data值相同的结点删除100条经典C语言笔试题目69、请写出下列代码的输出内容

#include<stdio.h>

main()

{

inta,b,c,d;

a=10;

b=a++;

c=++a;

d=10*a++;

printf("b,c,d:%d,%d,%d",b,c,d);

return0;

}

【标准答案】10,12,120100条经典C语言笔试题目70、找出程序的错误。

100条经典C语言笔试题目71、一语句实现x是否为2的若干次幂的判断。【参考答案】voidmain(){ inta; scanf(“%d”,&a); printf(“%c”,(a)&(a-1)?’n’:’y’);//若是打印y,n}100条经典C语言笔试题目72、编写一个C函数,该函数在一个字符串中找到可能的最长的子字符串,且该字符串是由同一字符组成的。100条经典C语言笔试题目73、下面的代码输出是什么,为什么?

voidfoo(void)

{

unsignedinta=6;

intb=-20;

(a+b>6)?puts(">6"):puts("<=6");

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

unsignedintzero=0;

unsignedintcompzero=0xFFFF;

/*1‘scomplementofzero*/【参考答案】对于一个int型不是16位的处理器为说,上面的代码是不正确的。应编写如下:

unsignedintcompzero=~0;

这一问题真正能揭露出应试者是否懂得处理器字长的重要性。在我的经验里,好的嵌入式程序员非常准确地明白硬件的细节和它的局限,然而PC机程序往往把硬件作为一个无法避免的烦恼。

100条经典C语言笔试题目75、下面的代码片段的输出是什么,为什么?

char*ptr;

if((ptr=(char*)malloc(0))==NULL)

puts("Gotanullpointer");

else

puts("Gotavalidpointer");

100条经典C语言笔试题目76、编写strcpy函数已知strcpy函数的原型是char*strcpy(char*strDest,constchar*strSrc);其中strDest是目的字符串,strSrc是源字符串。(1)不调用C++/C的字符串库函数,请编写函数strcpy。(2)strcpy能把strSrc的内容复制到strDest,为什么还要char*类型的返回值?100条经典C语言笔试题目77、编程实现:把十进制数(long型)分别以二进制输出,不能使用printf系列库函数。

100条经典C语言笔试题目78、请编写一个C函数,该函数给出一个字节中被置1的位的个数。unsigned

int

TestAsOne0(char

log)

{

int

i;

unsigned

int

num=0,

val;

for(i=0;

i<8;

i++)

{

val

=

log

>>

i;

//移位

val

&=

0x01;

//与1相与

if(val)

num++;

}

return

num;

}

100条经典C语言笔试题目79、请编写一个C函数,该函数将给定的一个字符串转换成整数。【参考答案】intInvert(char*str){ intnum=0; while(*str!='\0') { intdigital=*str-48; num=num*10+digital; str=str+1; }returnnum;}100条经典C语言笔试题目80、请编写一个C函数,该函数将给定的一个整数转换成字符串。void

IntToCharChange(int

num,

char*

pval)

{

char

strval[100];

int

i,

j;

int

val0

=

0;

int

val1

=

0;

val0

=

num;

for(i=0;

i<100;

i++)

{

val1

=

val0

%

10;

//取余

val0

=

val0

/

10;

//取整

strval[i]

=

val1

+

48;

//数字—字符

if(val0

<

10)

{

i++;

strval[i]

=

val0

+

48;

break;

}

}

for(j=0;

j<=i;

j++)

//倒置

pval[j]

=

strval[i-j];

pval[j]

=

'\0';

}100条经典C语言笔试题目81、用递归算法判断数组a[N]是否为一个递增数组。。

100条经典C语言笔试题目82、请编写一个C递归

函数,该函数将一个字符串逆序。100条经典C语言笔试题目83、请编写一个C函数,该函数在给定的内存区域搜索给定的字符,并返回该字符所在位置索引值。intsearch(char*cpSource,intn,charch)//起始地址,搜索长度,目标字符

{

inti;

for(i=0;i<n&&*(cpSource+i)!=ch;++i);

returni;

}100条经典C语言笔试题目84、请编写一个C函数,该函数在一个字符串中找到可能的最长的子字符串,该字符串是由同一字符组成的。

intChildStr

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论