嵌入式c语言开发修炼(精选5篇)
1.嵌入式c语言开发修炼 篇一
华硕_嵌入式程序员C语言笔试题目
预处理器(Preprocessor).用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)
#define SECONDS_PER_YEAR(60 * 60 * 24 * 365)UL
我在这想看到几件事情:
1)#define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)
2)懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。
3)意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。
4)如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。记住,第一印象很重要。.写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。
#define MIN(A,B)((A)<=(B)?(A):(B))
这个测试是为下面的目的而设的:
1)标识#define在宏中应用的基本知识。这是很重要的。因为在 嵌入(inline)操作符 变为标准C的一部分之前,宏是方便产生嵌入代码的唯一方法,对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。
2)三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生比if-then-else更优化的代码,了解这个用法是很重要的。
3)懂得在宏中小心地把参数用括号括起来
4)我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什么事?
least = MIN(*p++, b);
3.预处理器标识#error的目的是什么?
Error directives produce compiler-time error messages.死循环(Infinite loops)
4.嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢?
这个问题用几个解决方案。我首选的方案是:
while(1){ }
一些程序员更喜欢如下方案:
for(;;){ }
这个实现方式让我为难,因为这个语法没有确切表达到底怎么回事。如果一个应试者给出这个作为方案,我将用这个作为一个机会去探究他们这样做的基本原理。如果他们的基本答案是:“我被教着这样做,但从没有想到过为什么。”这会给我留下一个坏印象。
第三个方案是用 goto Loop:...goto Loop;
应试者如给出上面的方案,这说明或者他是一个汇编语言程序员(这也许是好事)或者他是一个想进入新领域的BASIC/FORTRAN程序员。
数据声明(Data declarations)
5.用变量a给出下面的定义
a)一个整型数(An integer)
b)一个指向整型数的指针(A pointer to an integer)c)一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to a pointer to an intege)r
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
人们经常声称这里有几个问题是那种要翻一下书才能回答的问题,我同意这种说法。当我写这篇文章时,为了确定语法的正确性,我的确查了一下书。但是当我被面试的时候,我期望被问到这个问题(或者相近的问题)。因为在被面试的这段时间里,我确定我知道这个问题的答案。应试者如果不知道所有的答案(或至少大部分答案),那么也就没有为这次面试做准备,如果该面试者没有为这次面试做准备,那么他又能为什么出准备呢? Static
6.关键字static的作用是什么?
这个简单的问题很少有人能回答完全。在C语言中,关键字static有三个明显的作用:
1)在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。
2)在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。
3)在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。
大多数应试者能正确回答第一部分,一部分能正确回答第二部分,同是很少的人能懂得第三部分。这是一个应试者的严重的缺点,因为他显然不懂得本地化数据和代码范围的好处和重要性。
Const
7.关键字const有什么含意?
我只要一听到被面试者说:“const意味着常数”,我就知道我正在和一个业余者打交道。去年Dan Saks已经在他的文章里完全概括了const的所有用法,因此ESP(译者:Embedded Systems Programming)的每一位读者应该非常熟悉const能做什么和不能做什么.如果你从没有读到那篇文章,只要能说出const意味着“只读”就可以了。尽管这个答案不是完全的答案,但我接受它作为一个正确的答案。(如果你想知道更详细的答案,仔细读一下Saks的文章吧。)
如果应试者能正确回答这个问题,我将问他一个附加的问题:
下面的声明都是什么意思?
const int a;
int const a;
const int *a;
int * const a;
int const * const a=new int(1);
/******/
前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意识a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。如果应试者能正确回答这些问题,那么他就给我留下了一个好印象。顺带提一句,也许你可能会问,即使不用关键字 const,也还是能很容易写出功能正确的程序,那么我为什么还要如此看重关键字const呢?我也如下的几下理由:
1)关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清理的。)
2.嵌入式c语言开发修炼 篇二
1ARM和嵌入式系基本概念
嵌入式系统也就是说嵌入式计算机系统, 可以使用在大型厂房或者机器装置进行监控中, 相比较普通计算机系统来说, 存在以下几方面优势: 第一, 计算机系统主要面对的就是大部分行业和大众, 但是嵌入式计算机系统主要面向的是一些特定应用; 第二, 一般来说计算机软件大部分都是储存在硬盘或者磁盘中, 但是嵌入式计算机软件大部分存储在单片机或者存储器芯片上[1]; 第三 , 一般情况下 , 嵌入式计算机系统需要一定比较专业的编程环境和开发工具, 与计算机系统相类似, 嵌入式计算机系统包括应用软件和操作软件, 由此可发现, 其中基本结构主要包括了嵌入式外围设备、 嵌入式处理器、 嵌入式应用软件、 嵌入式操作系统, 嵌入式处理器实际上与计算机CPU类似, 属于系统核心部分。 侵入式处理器中最重要的就是ARM系类处理器, 具备功耗 低 、 速度快、 价格低等特点, 使其拥有广阔的应用前景, 现阶段已经在通信系统、 电子产品和军事系统中得到广泛运用。
2main函数和系统引导
一般来说, C语言都是从main函数开始进行的, main函数的基本原型就是: Int main (int argc, char***argv), argv表示参数个数, argv表示各项参数指针数组。 利用操作系统的内核来启动main函数, 系统内核主要就是能否为初始化变量提供函数, 并且能够在完成调用以后, 检查函数的返回值, 如果返回值是0, 说明程序可以正常运行, 否则说明程序存在错误[2]。 在嵌入式系统中 , 如果没有一定的操作系统内核 , 智能通过系统引导来完成初始化main函数的工作。 在系统引导部分合理完成初始化以后, 通过汇编语言来达到目的。 主要工作包括初始化硬件、 设置寄存器、 初始化全局变量、 加载mai运行模块、 初始化堆参数。 完成上述工作以后, 需要在C语言的main函数中运用控制权, 对于main函数来说, argv和arge参数和返回值没有实际意义。 此外, 为了避免出现混淆问题, 需要给main函数重新取名, 否则, 会使得编译器形成很多初始化代码, 导致接错系统引导模块和C程序入口。
3函数局数变量个数
为了能够提高执行程序的速度, 在编译函数的时候, 在寄存器中合理分配局部变量。 如果局部变量多余寄存器的时候, 编译器会适当把多出来的变量存入到存储器中, 所以, 需要合理控制局部变量的个数[3]。 AMR处理器主 要使用的 就是RISC结构 , 并且具有 很多的内 部寄存器 。 编译器需 要合理运 用APCS开关选项 , 也就是能够符合ATPCS标准 , 从理论上来说, 具备14个寄存器可以适当存储局部变量。 在实际使用的过程中, 由于自身具备一定的特殊性, R9在读取与位置相关语言的时候, 可以当做静态基址寄存器, R12可以被当做子程序来调用内部临时寄存器, 以此, 需要合理限制局部变量数目。
4LCD终端和存储器管
4.1LCD终端
系统I/O重要内容 实际上就 是LCD终端如阿 健 , 包括LCD绘图 、 LCD字符显示 、 320*240像素LCD显示器 , 可以显示5行 *20列的汉字字符或者15行 *40列的英文字符, 具有比较良好的分辨率图像现实功能[4]。
4.2存储管理
从广义上来说, 存储管理包括内存、 磁盘文件系统、 片内高速Cacge等, 在嵌入式系统中, 最有意义的实际上就是适当和分配内存动态和管理Flash存储器。 C语言系统中, 释放和分配动态内存的时候, 主要利用free和malloc标准库函数实现 。 Malloc可以从系 统内存空 闲空间中 合理分配 内存块 , free可以完成回回收内存块的作用 , 上述两种函数需要相应的系统内核, 在ARM系统平台上, 不可以直接进 行调用 , 因此, 需要适当编写m-free和m-alloc函数, 以便于达到动态存储管理的目的。
5设计应用程序和驱动程序
5.1驱动程序
驱动程序主要包括两大部分, 最底层中断处理器以及处理器上的驱动程序, 实现设计驱动程序与外围设备息息相关, 具有一定复杂性。 在设计C语言驱动程序的时候, 需要注意以下方面: 一般来说, 利用中断来连接外围设备和CPU。 中断属于外部异步事件, 在设计过程中, 处理和中断有关程序的时候, 需要谨慎小心。 设计C语言编程的时候还需要考虑效率, 如, 操作对数组元素的时候, Array [idx/4] =&~1, 可以适当变为Array [idx>>2] =&~1,其中>>属于移位运算, 具有比较复杂的算法, 现在存在的先进编辑器能够合理优化上述语句, 但是并不是所有设备都具有以上功能[5]。
5.2应用程序
在设计嵌入式应用程序的时候, 与计算机应用程序存在很多不同的地方, 需要密切注意。 第一, 不能使用操作系统支持的标准函数, 可以自己进行编写, 例如, m-free。 第二, 具有有限内存资源的时候, 存在有限栈容量, 还不能进行自动扩展, 使用的时候要小心。 第三, 不可以使用递 归函数 。第四, 不能忽略编译器的警告信息, 如果编译人员具有良好的素质, 是不会忽略任何警告的, 一般来说, 出警告信息往往存在比较严重的逻辑错误[6]。
6结语
主要分析了嵌入式系统中比较具有代表性的C语言编程和嵌入式系统, 此外还介绍了嵌入式系统应用程序设计, 上述过程中, 会出现不能直接借用内部资源的问题, 导致限制容量, 使得在设计扩展的时候出现困难, 在系统中应用C语言编程方式可以很好地解决上述问题, 随着不断发展和日渐成熟的C语言编程方式, 为其ARM嵌入式系统发展提供了依据和保障。
参考文献
[1]高永平.嵌入式DSP系统C语言硬件编程技术[J].电子制作,2014,(13):65-66.
[2]过怡.基于ARM的高效C语言编程[J].单片机与嵌入式系统应用,2010,(8):74-75.
[3]甄华.基于ARM嵌入式系统的C语言编程分析[J].哈尔滨职业技术学院学报,2015,(1):148-149.
[4]孙婧.ARM嵌入式系统C语言编程分析[J].计算机光盘软件与应用,2011,(18):215-215.
[5]李丽萍.基于ARM嵌入式系统的C语言编程初探[J].电子测试,2014,(13):3-4.
3.嵌入式c语言开发修炼 篇三
【关键词】Cortex-M3;?C/OS-II;嵌入式系统开发与应用;本科教学
1.引言
ARM是目前嵌入式领域应用最广泛的RISC微处理器,它以低成本、低功耗、高性能等优点占据了嵌入式系统应用领域的领先地位。当前ARM系列的处理器有ARM7、ARM9、ARM9E、ARM10、ARM11等多个产品。Cortex-M3内核是ARM公司于2006年推出的一款高性能处理器内核,是ARM新型V7指令集结构系列的微控制器版本,可用于企业应用、汽车系统、家庭网络和无线技术等领域。其主要特点是:
(1)功耗低;
(2)内核的门数少,具有优异的性价比;
(3)中断延时短;
(4)调试成本低;
(5)具有嵌套向量中断控制器(NVIC),与处理器内核紧密结合实现低延迟的中断处理;
(6)具有可裁减的存储器保护单元(MPU),用于对存储器进行保护。
Cortex-M3内核的处理器本身的资源不是特别复杂,特别适合高等院校本科生对ARM的体系结构学习,可移植小型开源操作系统UCOS-II,能加深学生对嵌入式操作系统认识。
2.Cortex-M3+?C/OS-II嵌入式系统开发与应用教学内容
《Cortex-M3+?C/OS-II嵌入式系统开发与应用》课程是电子信息类的一门专业课。该课程的主要任务是:通过本课程的学习,使学生对嵌入式系统原理与技术有系统的、全面的了解;掌握嵌入式处理器的概念、组成和体系结构特点;通过对?C/OS-II详细剖析,掌握RTOS实时操作的原理,对其内核结构、任务调度等有深入的了解,培养嵌入式系统的设计和开发应用能力。
通过学习本课程后,应达到下列基本要求:
(1)具有一定的计算机体系结构、操作系统、接口与通信等专业基础理论知识;
(2)熟悉基于Cortex-M3架构的微处理器体系结构及应用特点,用?C/OS-II进行应用开发的技术点;
(3)了解LCD、UART、IIS、I2C等常用外设的设计和开发,为实际应用开发打下基础。
3.Cortex-M3+?C/OS-II嵌入式系统开发与应用教学的难点
学习嵌入式的重点和难点关键在操作系统,如果没有掌握操作系统,笔者认为很难把握一个嵌入式系统。即使在做嵌入式开发中,作应有层的开发几乎可以不知道操作系统也可以开发,那是浮在表面的,很难深入和提高自己的层次。选择μc/os-II这样的小型操作系统,对本科教学最为合适。本课程教学的难点在于:
(1)Cortex-M3指令集
ARM7、ARM9内核都支持有ARM指令集和Thumb指令集,目前的Cortex-M3内核是Thumb-2指令集。了解Thumb-2指令集,可以更深层次的理解Cortex-M3的启动过程。
(2)μc/os-II操作系统
实时操作系统μC/OS-II是一个基于优先级的抢占式实时内核,程序可读性强,移植性好,代码固定,可裁剪,非常灵活。至今,从8位到64位,μC/OS-II已在超过40种不同架构的微处理器上运行。μC/OS-II的主要特点有:是优先级可剥夺的实时多任务操作系统;可处理和调度56个用户任务,任务的优先级可以动态调整;提供任务间通信、同步使用的信号量、邮箱和消息队列;具有良好的可裁剪性,可尽量减小系统的ROM和RAM大小。
(3)寄存器配置
Cortex-M3系列微处理器,可以有众多的片内外设。不同的需求有不同的配置,它的寄存器配置是学习中的重点与难点。
4.Cortex-M3+?C/OS-II嵌入式系统开发与应用教学与实验方法
首先改善教学方法。考虑到目前的本科课程门类已大为增加,任何一门非公共课的学时都不会很多。显然,突出要点才能更有效。建议这门课可安排32学时理论课,另加16学时实验课。这就要求主要以引导性教学为主。例如对嵌入式系统的教学就不能像C或汇编语言那样逐条语句讲授,而是应结合具体实例讲解寄存器配置与片内外设接口。
其次是注重教学实践性。本课程具有很强的实践性。针对性强的实验应该是教学的重要环节,嵌入式系统实验更应注重实验质量,而决非仅使用ARM开发软件。先熟悉开发环境,但这并非嵌入式系统实验的关键。因为ST公司对Cortex-M3的大力开发,有很多库文件,给开发者带来很大的便利。如全国大学生电子设计竞赛时间短,编程量大,程序结构让参赛者陷入困境,选择Cortex-M3的系统可以加快开发速度。因此,嵌入式系统课程的实验,除了必须完成的基础性项目外,引导学生完成一些传统单片机不能实现的内容,从而突出Cortex-M3系统设计的优势。例如TFT LCD显示+触摸屏,重点在人机界面;UART、PS/2或USB接口,关注通信协议与寄存器配置;μC/OS-II应用突出了实时操作系统的多任务操作实现等。在这些实践过程中,会使学生发现,诸如ISP下载方式、ARM指令与寄存器等本身都成了配角,而唯有更高质地完成实验项目而不懈追求的设计能动性和创造性成了主角,从而有效提高这门以培养工程实践能力为主的教学效果。
再次就是注重实用。教学内容上,在讲清内容的同时,对每部分内容均需安排有针对性的教学实验。对设置的大部分的实验除给出详细的实验目的、实验原理、实验思考题和实验报告要求外,还应包含3种实验项目,即:基础实验项目是与该部分内容相关的接口实验,对于该部分实验,学生只须将提供的程序输入到计算机,并按要求进行编译通过,并在实验系统上实现即可;功能实验项目是在上一实验基础上进一步发挥性实验;系统实验项目属于自主设计或创新性质的实验。这样,学生就可以循序渐进进行多层次的实验项目。
最后,注重系统调试。一般认为嵌入式系统技术难点和学习费时的根源在于存储器配置。对此,根据电子类专业的特点,教师需放弃流行的ARM的教学模式,放弃常规的教学思路,以ARM体系结构为基点,从实例介绍中引出寄存器配置内容,通过少数几个简单、直观、典型的实例将寄存器配置中最核心、最基本的内容解释清楚,使学生在很短的时间内就能有效地把握片上外设的配置,而不必花费大量的时间去“系统地”学习ARM指令与接口内容。要求教师从时间中抓效益,从效益中提高学生学习与研究能力的培养。
总之,高校教师需力争在不增加课时的情况下,保持嵌入式系统教学内容的系统性和完整性,使学生通过大量寄存器配置,掌握嵌入式系统开发方法。通过接口实验,初步掌握ARM技术最基本的内容。同时通过向几个典型实用示例的设计练习,使学生在只有微处理器基础知识的条件下即能迅速学会使用Cortex-M3库文件编程的设计方法和学会利用μc/os-II完成较复杂系统的多任务设计实验真正达到培养创新型人才培养的目的。
参考文献
[1]陈瑶等.Cortex-M3 +μC/OS-II嵌入式系统开发入门与应用[M].人民邮电出版社,2010.
[2]李宁.基于MDK的STM32处理器开发与应用[M].北京航空航天大学出版社,2008.
[3]李宁.ARM开发工具RealView MDK使用入门编著[M].北京航空航天大学出版社,2008.
[4]ARM Limited.Cortex-M3 Technical Reference Manual.2005.
本文获2012年上海理工大学重点课程建设基金资助(NO:20090702)。
4.嵌入式c语言开发修炼 篇四
char 一个字节 1 byte int 两个字节 2 byte(16位系统, 认为整型是2个字节)long int 四个字节 4 byte float 四个字节4 byet double 八个字节 8 byte long double 十个字节 10 byte pointer 两个字节 2 byte(注意, 16位系统, 地址总线只有16位)第1题: 考查对volatile关键字的认识 #include static jmp_buf buf;main(){ volatile int b;b =3;if(setjmp(buf)!=0){ printf(“%d “, b);exit(0);} b=5;longjmp(buf , 1);} 请问, 这段程序的输出是(a)3(b)5(c)0(d)以上均不是 第2题:考查类型转换 main(){ struct node { int a;int b;int c;};struct node s= { 3, 5,6 };struct node *pt = &s;printf(“%d” , *(int*)pt);} 这段程序的输出是:(a)3(b)5(c)6(d)7 第3题:考查递归调用 int foo(int x , int n){ int val;val =1;if(n>0){ if(n%2 == 1)val = val *x;val = val * foo(x*x , n/2);} return val;} 这段代码对x和n完成什么样的功能(操作)?(a)x^n(x的n次幂)(b)x*n(x与n的乘积)(c)n^x(n的x次幂)(d)以上均不是
第4题:考查指针,这道题只适合于那些特别细心且对指针和数组有深入理解的人 main(){ int a[5] = {1,2,3,4,5};int *ptr =(int*)(&a+1);printf(“%d %d” , *(a+1), *(ptr-1));} 这段程序的输出是:(a)2 2(b)2 1(c)2 5(d)以上均不是
第5题:考查多维数组与指针 void foo(int [][3]);main(){ int a [3][3]= { { 1,2,3} , { 4,5,6},{7,8,9}};foo(a);printf(“%d” , a[2][1]);} void foo(int b[][3]){ ++ b;b[1][1] =9;} 这段程序的输出是:(a)8(b)9(c)7(d)以上均不对 第6题:考查逗号表达式 main(){ int a, b,c, d;a=3;b=5;c=a,b;d=(a,b);printf(“c=%d” ,c);printf(“d=%d” ,d);} 这段程序的输出是:(a)c=3 d=3(b)c=5 d=3(c)c=3 d=5(d)c=5 d=5 第7题:考查指针数组 main(){ int a[][3] = { 1,2,3 ,4,5,6};int(*ptr)[3] = a;printf(“%d %d “,(*ptr)[1],(*ptr)[2]);++ptr;printf(“%d %d” ,(*ptr)[1],(*ptr)[2]);} 这段程序的输出是:(a)2 3 5 6(b)2 3 4 5(c)4 5 0 0(d)以上均不对 第8题:考查函数指针 int *f1(void){ int x =10;return(&x);} int *f2(void){ int*ptr;*ptr =10;return ptr;} int *f3(void){ int *ptr;ptr=(int*)malloc(sizeof(int));return ptr;} 上面这3个函数哪一个最可能引起指针方面的问题(a)只有 f3(b)只有f1 and f3(c)只有f1 and f2(d)f1 , f2 ,f3 第9题:考查自加操作(++)main(){ int i=3;int j;j = sizeof(++i+ ++i);printf(“i=%d j=%d”, i ,j);} 这段程序的输出是:(a)i=4 j=2(b)i=3 j=2(c)i=3 j=4(d)i=3 j=6 第10题:考查形式参数, 实际参数, 指针和数组 void f1(int *, int);void f2(int *, int);void(*p[2])(int *, int);main(){ int a;int b;p[0] = f1;p[1] = f2;a=3;b=5;p[0](&a, b);printf(“%dt %dt”, a, b);p[1](&a, b);printf(“%dt %dt”, a, b);} void f1(int* p , int q){ int tmp;tmp =*p;*p = q;q= tmp;} void f2(int* p , int q){ int tmp;tmp =*p;*p = q;q= tmp;} 这段程序的输出是:(a)5 5 5 5(b)3 5 3 5(c)5 3 5 3(d)3 3 3 3 第11题:考查自减操作(–)void e(int);main(){ int a;a=3;e(a);} void e(int n){ if(n>0){ e(–n);printf(“%d”, n);e(–n);} } 这段程序的输出是:(a)0 1 2 0(b)0 1 2 1(c)1 2 0 1(d)0 2 1 1 第12题:考查typedef类型定义,函数指针 typedef int(*test)(float * , float*)test tmp;tmp 的类型是
(a)函数的指针, 该函数以两个指向浮点数(float)的指针(pointer)作为参数(arguments)Pointer to function of having two arguments that is pointer to float(b)整型(c)函数的指针, 该函数以两个指向浮点数(float)的指针(pointer)作为参数(arguments),并且函数的返回值类型是整型 Pointer to function having two argument that is pointer to float and return int(d)以上都不是
第13题:数组与指针的区别与联系 main(){ char p;char buf[10] ={ 1,2,3,4,5,6,9,8};p =(buf+1)[5];printf(“%d” , p);} 这段程序的输出是:(a)5(b)6(c)9(d)以上都不对
第14题: 考查指针数组的指针 void f(char**);main(){ char * argv[] = { “ab” ,”cd” , “ef” ,”gh”, “ij” ,”kl” };f(argv);} void f(char **p){ char* t;t=(p+= sizeof(int))[-1];printf(“%s” , t);} 这段程序的输出是:(a)ab(b)cd(c)ef(d)gh 第15题:此题考查的是C的变长参数,就像标准函数库里printf()那样,这个话题一般国内大学课堂是不会讲到的,不会情有可原 #include int ripple(int ,);main(){ int num;num = ripple(3, 5,7);printf(” %d” , num);} int ripple(int n,){ int i , j;int k;va_list p;k= 0;j = 1;va_start(p, n);for(;j{ i = va_arg(p , int);for(;i;i &=i-1)++k;} return k;} 这段程序的输出是:(a)7(b)6(c)5(d)3 第16题:考查静态变量的知识 int counter(int i){ static int count =0;count = count +i;return(count);} main(){ int i , j;for(i=0;i <=5;i++)j = counter(i);} 本程序执行到最后,j的值是:(a)10(b)15(c)6(d)7 详细参考答案 第1题:(b)volatile字面意思是易于挥发的。这个关键字来描述一个变量时, 意味着 给该变量赋值(写入)之后, 马上再读取, 写入的值与读取的值可能不一样,所以说它“容易挥发”的。
这是因为这个变量可能一个寄存器, 直接与外部设备相连, 你写入之后, 该寄存器也有可能被外部设备的写操作所改变;或者, 该变量被一个中断程序, 或另一个进程 改变了.volatile 不会被编译器优化影响, 在longjump 后,它的值 是后面假定的变量值,b最后的值是5,所以5被打印出来.setjmp : 设置非局部跳转 /* setjmp.h*/ Stores context information such as register values so that the lomgjmp function can return control to the statement following the one calling setjmp.Returns 0 when it is initially called.Lonjjmp: 执行一个非局部跳转 /* setjmp.h*/ Transfers control to the statement where the call to setjmp(which initialized buf)was made.Execution continues at this point as if longjmp cannot return the value 0.A nonvolatile automatic variable might be changed by a call to longjmp.When you use setjmp and longjmp, the only automatic variables guaranteed to remain valid are those declared volatile.Note: Test program without volatile qualifier(result may very)更详细介绍, 请参阅 C语言的setjmp和longjmp 第2题:(a)结构题的成员在内存中的地址是按照他们定义的位置顺序依次增长的。如果一个结构体的指针被看成 它的第一个成员的指针,那么该指针的确指向第一个成员 第3题:(a)此题目较难.这个程序的非递归版本 int what(int x , int n){ int val;int product;product =1;val =x;while(n>0){ if(n%2 == 1)product = product*val;/*如果是奇数次幂, x(val)要先乘上一次,;偶数次幂, 最后返回时才会到这里乘以1*/ val = val* val;n = n/2;} return product;} /* 用二元复乘策略 */ 算法描述(while n>0){ if next most significant binary digit of n(power)is one then multiply accumulated product by current val, reduce n(power)sequence by a factor of two using integer division.get next val by multiply current value of itself } 第4题:(c)a的类型是一个整型数组,它有5个成员。&a的类型是一个整型数组的指针, 所以&a + 1指向的地方等同于a[6], 所以*(a+1)等同于a[1] ptr等同a[6], ptr-1就等同与a[5] 第5题:(b)题目自身就给了足够的提示 b[0][0] = 4 b[1][0] = 7 第6题:(c)考查逗号表达式,逗号表达式的优先级是很低的, 比 赋值(=)的优先级 低.逗号表达式的值就是最后一个元素的值
逗号表达式的还有一个作用就是分割函数的参数列表..E1, E2, …, En 上面这个表示式的左右是,E1, E2,… En的值被分别计算出来, En计算出来的结构赋给整个逗号表达式
c=a,b;/ *yields c=a* / d=(a,b);/* d =b */ 第7题:(a)ptr是一个数组的指针, 该数组有3个int成员 第8题:(c)f1显然有问题, 它返回一个局部变量的指针, 局部变量是保存在stack中的,退出函数后, 局部变量就销毁了, 保留其指针没有意义, 因为其指向的stack空间可能被其他变量覆盖了
f2也有问题, ptr是局部变量, 未初始化, 它的值是未知的, *ptr不知道指向哪里了, 直接给*ptr赋值可能会覆盖重要的系统变量, 这就是通常说的野指针的一种 第9题:(b)sizeof 操作符给出其操作数需要占用的空间大小, 它是在编译时就可确定的, 所以其操作数即使是一个表达式, 也不需要在运行时进行计算.(++i + ++ i)是不会执行的, 所以i的值还是3 第10题:(a)很显然选a.f1交换*p 和 q的值, f1执行完后, *p 和 q的值的确交换了, 但q的改变不会影响到b的改变, *p 实际上就是a 所以执行f1后, a=b=5 这道题考查的知识范围很广,包括typedef自定义类型,函数指针,指针数组void(*p[ 2 ])(int *, int);定义了一个函数指针的数组p,p有两个指针元素.元素是函数的指针, 函数指针指向的函数是一个带2个参数,返回void的函数, 所带的两个参数是指向整型的指针, 和整型
p[ 0 ] = f1;p[ 1 ] = f2 contain address of function.function name without parenthesis represent address of function Value and address of variable is passed to function only argument that is effected is a(address is passed).Because of call by value f1, f2 can not effect b 第11题:(a)考查–操作和递归调用,仔细分析一下就可以了 第12题:(c)建议不会的看看C专家编程
从左往有, 遇到括号停下来, 将第一个括号里的东西看成一个整体 第13题:(c)考查什么时候数组就是指针.对某些类型T而言, 如果一个表达式是 T[](T的数组), 这个表达式的值实际上就是指向该数组的第一个元素的指针.所以(buf+1)[5]实际上就是*(buf +6)或者buf[6] 第14题:(b)sizeof(int)的值是2,所以p+=sizeof(int)指向 argv[2],这点估计大家都没有什么疑问(p+=sizeof(int))[-1] 指向 argv[1],能理解吗, 因为(p+=sizeof(int))[-1] 就相当于(p+=2)[-1] ,也就是(p+2-1)第15题:(c)在C编译器通常提供了一系列处理可变参数的宏, 以屏蔽不同的硬件平台造成的差异, 增加程序的可移植性。这些宏包括va_start、va_arg和va_end等。
采用ANSI标准形式时, 参数个数可变的函数的原型声明是:type funcname(type para1, type para2, …)这种形式至少需要一个普通的形式参数, 后面的省略号不表示省略, 而是函数原型的一部分。type是函数返回值和形式参数的类型。
不同的编译器, 对这个可变长参数的实现不一样 , gcc4.x中是内置函数.关于可变长参数,可参阅
5.五子棋游戏开发总结(C语言版) 篇五
一.五子棋游戏概述
略
二.游戏功能
对弈游戏,自动判断游戏胜负。
采用人机对话模式,界面设计美观友好。
具体玩法:采用任意键开始游戏,此处采用键盘值W、A、S、D控制棋子移动方向,空格键(SPACE)落子,ESC退出游戏。
三.系统开发平台
1)Visual C++ 单纯的Visual C++ 不行,需下载一个EasyX小插件对其进行配置好才可(网上有下的,也有配置方法)。2)程序代码必须以.cpp结尾。
3)最佳分辨率:最佳效果1024*768。四. 游戏开发详细过程:
五.游戏的完整详细代码:
#include
#include
//图形库 #include
#include
#define ESC 27
//退出
#define SPACE 32
#define LEFT 65
//向左键 #define RIGHT 68 #define UP 87 #define DOWN 83
int key;
int chess[20][20];
//棋盘坐标位置
int flag=1;//标识要画的棋子的颜色flag=1,棋子为蓝色;其他为红色。int chessx,chessy;
void start();void draw_chessboard();void draw_circle(int x,int y,int color);void play();
int result(int x,int y);//开始游戏 void start(){
outtextxy(200,240,“GAME START!”);
outtextxy(200,380,“ESC-exit/press any key to continue ”);} //画棋盘
void draw_chessboard(){
int i,j;
setbkcolor(GREEN);//设置背景颜色为绿色
cleardevice();//清屏
for(i=40;i<=440;i+=20)
for(j=40;j<=440;j++)
{
putpixel(i,j,4);
putpixel(j,i,4);
}
setcolor(8);
setlinestyle(1,0,1);
rectangle(32,32,448,448);
outtextxy(10,10,“ESC-exit/SPACE-put a piece”);} //画棋子
void draw_circle(int x,int y,int color){
setcolor(color);
setlinestyle(1,0,10);
x=(x+2)*20;
y=(y+2)*20;
circle(x,y,4);} //清除棋子
void draw_pixel(int x,int y,int color){
x=(x+2)*20;
y=(y+2)*20;
{
int a,b,c,d;
for(a=1;a<=8;a++)
putpixel(x+a,y,color);
for(b=8;b>=1;b--)
putpixel(x,y-b,color);
for(c=1;c<=8;c++)
putpixel(x,y+c,color);
for(d=8;d>=1;d--)
putpixel(x-d,y,color);
putpixel(x+9,y,color);
putpixel(x,y-9,color);
putpixel(x,y+9,color);
putpixel(x-9,y,color);
} } //游戏过程 void play(){
int i,j;
switch(key)
{
case LEFT://棋子左移
if(chessx-1<0)
break;
else
{
for(i=chessx-1,j=chessy;i>=1;i--)
if(chess[i][j]==0)
{
draw_circle(chessx,chessy,GREEN);
draw_pixel(chessx,chessy,8);
break;
}
if(i<1)
break;
chessx=i;
if(flag==1)
draw_circle(chessx,chessy,BLUE);
else
draw_circle(chessx,chessy,RED);
}
break;
case RIGHT://棋子右移
if((chessx+1)>19)
break;
else
{
for(i=chessx+1,j=chessy;i<=19;i++)
if(chess[i][j]==0)
{
draw_circle(chessx,chessy,GREEN);
draw_pixel(chessx,chessy,8);
break;
}
if(i>19)
break;
chessx=i;
if(flag==1)
draw_circle(chessx,chessy,BLUE);
else
draw_circle(chessx,chessy,RED);
}
break;
case DOWN://棋子下移
if((chessy+1)>19)
break;
else
{
for(i=chessx,j=chessy+1;j<=19;j++)
if(chess[i][j]==0)
{
draw_circle(chessx,chessy++,GREEN);
draw_pixel(chessx,chessy,8);
break;
}
if(j>19)
break;
chessx=i;
if(flag==1)
draw_circle(chessx,chessy,BLUE);
else
draw_circle(chessx,chessy,RED);
}
break;
case UP://棋子上移
if((chessy-1)<0)
break;
else
{
for(i=chessx,j=chessy-1;j>=1;j--)
if(chess[i][j]==0)
{
draw_circle(chessx,chessy,GREEN);
draw_pixel(chessx,chessy,8);
break;
}
if(j<1)
break;
chessy=j;
if(flag==1)
draw_circle(chessx,chessy,BLUE);
else
draw_circle(chessx,chessy,RED);
}
break;
case ESC://退出游戏
break;
case SPACE://落子
if(chessx>=1&&chessy<=19&&chessx<19&&chessy>=1)
{
if(chess[chessx][chessy]==0)
{
chess[chessx][chessy]=flag;
if(result(chessx,chessy)==1)
{
cleardevice();
if(flag==1)
{
cleardevice();
outtextxy(80,200,“CONGRATIONATIONS,BLUE WIN!”);
getch();
closegraph();
exit(0);
}
if(flag==2)
{
cleardevice();
outtextxy(80,200,“CONGRATIONATIONS,RED WIN!”);
getch();
closegraph();
exit(0);
}
}
if(flag==1)
flag=2;
else
flag=1;
break;
}
}
else
break;
} } //判断胜负
int result(int x,int y){
int j,k,n1,n2;
while(1)
{
n1=0;
n2=0;
for(j=x,k=y;j>=1&&k>=1;j--,k--)
{
if(chess[j][k]==flag)
n1++;
else
break;
}
for(j=x,k=y;j<=19&&k<=19;j++,k++)
{
if(chess[j][k]==flag)
n2++;
else
break;
}
if(n1+n2-1>=5)
return(1);
n1=0;
n2=0;
for(j=x,k=y;j<=19&&k>=1;j++,k--)
{
if(chess[j][k]==flag)
n1++;
else
break;
}
for(j=x,k=y;j>=1&&k<=19;j--,k++)
{
if(chess[j][k]==flag)
n2++;
else
break;
}
if(n1+n2-1>=5)
return(1);
n1=0;
n2=0;
for(j=x,k=y;j>=1;j--)
{
if(chess[j][k]==flag)
n1++;
else
break;
}
for(j=x,k=y;j<=19;j++)
{
if(chess[j][k]==flag)
n2++;
else
break;
}
if(n1+n2-1>=5)
return(1);
n1=0;
n2=0;
for(j=x,k=y;k>=1;k--)
{
if(chess[j][k]==flag)
n1++;
else
break;
}
for(j=x,k=y;k<=19;k++)
{
if(chess[j][k]==flag)
n1++;
else
break;
}
if(n1+n2-1>=5)
return(1);
return(0);
} }
//主函数
int main(void){
initgraph(620,480);
start();
key=getch();
if(key==ESC)
exit(0);
else
{
cleardevice();
flag=1;
draw_chessboard();
do
{
chessx=10;
chessy=10;
if(flag==1)
draw_circle(chessx,chessy,BLUE);
else
draw_circle(chessx,chessy,RED);
do
{
while(getch()==0);
key=getch();
play();
}
while(key!=ESC&&key!=SPACE);
}
while(key!=ESC);
closegraph();
}
return 0;}
【嵌入式c语言开发修炼】推荐阅读:
嵌入式系统c语言编程该怎么学?08-12
嵌入式Linux系统开发教程实验报告09-11
嵌入式产品开发工程师简历11-02
嵌入式软硬件开发毕业生简历09-16
嵌入式课程总结08-09
嵌入式软件求职简历08-06
嵌入式心得体会11-23
嵌入式系统就业前景06-16
嵌入式学习心得体会09-28
嵌入式系统实习报告11-09