关于嵌入式单片机 汇编 c语言c语言 有关于 char 数组 字符串 和 字符数组的问题

5272人阅读
单片机(3)
说明:原创都是个人经验,本人才疏学浅,如有不妥之处切盼高手指点纠正!
&&&&& &今天在做单片机的一个小程序,本来以为改一改例子程序很简单,结果耗费了一一整天时间。程序中用了很多strcat函数对字符串进行拷贝,我为了增强程序的通用性,就把原来字符串的地方用char数组代替。结果出现了很多意想不到的问题,输出字符混乱,系统重启等等。经过自己分析才发现strcat函数在作怪。C程序里规定字符串数组以\0作为结束符,也就是说strcat函数的操作只有在收到结束符才停止,如果不停止则胡乱寻址,程序不错才怪呢。
&&& strlen,strcat,strcpy等函数是以\0即0x00为结束符标识。而在实际应用中,总不能每次都在字符串后面跟个\0字符吧,在一些需要转换类型的场合很不实用。
&&& 为了摆脱这个限制,可以使用strncpy,strncat 这一类函数来操作,根据len来决定拷贝和附加的长度。以strncpy函数举例
char *strncpy ( char *dst, /* destination string */
&&&&&&&&&&&&&&&&&&&&&&&&& char *src, /* source string */
&&&&&&&&&&&&&&&&&&&&&&&&&&&int len); /* max characters to copy */)
原文的表述:The strncpy function copies at most len characters fromsrc todst. Characters are copied until a null character ('\0') is copied or untillen characters
have been copied. If the length ofsrc is less thanlen the remaining bytes in
dst are padded with null characters ('\0').
&& 注:*pStrInf=strstr(buf,&=&);//返回指针是&=&的起始地址,即包含&=&.
&& 其中这里特别说明一下:strcat和strcpy的区别,都是拷贝函数,Strcat是附加在源字符串的后面,而strcpy函数是从源字符串的0地址开始拷贝!!
&& 为了以后自己不犯错同样错误,记录下来,也希望能帮助到别人。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:180895次
积分:1942
积分:1942
排名:第13953名
原创:40篇
转载:22篇
评论:45条
(1)(2)(4)(1)(4)(1)(3)(1)(2)(1)(1)(4)(4)(6)(1)(1)(1)(1)(2)(4)(3)(1)(4)(4)(5)c语言在单片机开发中的几个问题_单片机_中国百科网
c语言在单片机开发中的几个问题
    在单片机的开发应用中,已逐渐开始引入高级语言,c语言就是其中的一种。对用惯了汇编的人来说,总觉得高级语言’可控性’不好,不如汇编那样随心所欲。但是只要我们掌握了一定的c语言知识,有些东西还是容易做出来的,以下是笔者实际工作中遇到的几个问题,希望对初学c51者有所帮助。一、c51热启动代码的编制对于工业控制计算机,往往设有有看门狗电路,当看门狗动作,使计算机复位,这就是热启动。热启动时,一般不允许从头开始,这将导致现有的已测量到或计算到的值复位,导致系统工作异常。因而在程序必须判断是热启动还是冷启动,常用的方法是:确定某内存单位为标志位(如0x7f位和0x7e位),启动时首先读该内存单元的内容,如果它等于一个特定的值(例如两个内存单元的都是0xaa),就认为是热启动,否则就是冷启动,程序执行初始化部份,并将0xaa赋与这两个内存单元。根据以上的设计思路,编程时,设置一个指针,让其指向特定的内存单元如0x7f,然后在程序中判断,程序如下:void main(){ char data *hotpoint=(char *)0x7f;if((*hotpoint==0xaa)&&(*(--hotpoint)==0xaa)){ /*热启动的处理 */}else{ hotpoint=0x7e; /*冷启动的处进*hotpoint=0*(++hotpoint)=0}/*正常工作代码*/}然而实际调试中发现,无论是热启动还是冷启动,开机后所有内存单元的值都被复位为0,当然也实现不了热启动的要求。这是为什么呢?原来,用c语言编程时,开机时执行的代码并非是从main()函数的第一句语句开始的,在main()函数的第一句语句执行前要先执行一段’起始代码’。正是这段代码执行了清零的工作。c编译程序提供了这段起始代码的源程序,名为cstartup.a51,打开这个文件,可以看到如下代码:.idatalen equ 80 the length of idata memory in bytes..startup1:if idatalen &> 0mov r0,#idatalen - 1clr aidataloop: mov @r0,adjnz r0,idataloopendif.可见,在执行到判断是否热启动的代码之前,起始代码已将所有内存单元清零。如何解决这个问题呢?好在启动代码是可以更改的,方法是:修改 startup.a51源文件,然后用编译程序所附带的a51.exe程序对 startup.a51编译,得到startup.obj文件,然后用这段代码代替原来的起始代码。具体步骤是(设c源程序名为hotstart.c):修改startup.a51源文件(这个文件在c51\lib目录下)。执行如下命令:a51 startup.a51 得到startup.obj文件。将此文件拷入hotstart.c所在目录。将编好的c源程序用c51.exe编译好,得到目标文件hotstart.obj。用 l51 hotstart, startup.obj 命令连接,得到绝对目标文件hotstart。用 ohs51 hotstart 得到hotstart.hex文件,即可。对于startup.a51的修改,根据自已的需要进行,如将idatalen equ 80h中的80h改为70h,就可以使6f到7f的16字节内存不被清零。二、直接调用eprom中已固化的程序笔者用的仿真机,由6位数码管显示,在内存de00h处放显示子程序,只要将要显示的数放入显示缓冲区,然后调用这个子程序就可以使用了,汇编指令为:lcall 0deooh在用c语言编程时,如何实现这一功能呢?c语言中有指向函数的指针这一概念,可以利用这种指针来实现用函数指针调用函数。指向函数的指针变量的定义格式为:类型标识符 (*指针变量名)();在定义好指针后就可以给指针变量赋值,使其指向某个函数的开始存地址,然后用(*指针变量名)()即可调用这个函数。如下例:void main(void){void (*dispbuffer)(); /*定义指向函数指针*/dispbuffer=0xde00; /*赋值*/for(;;){ key();dispbuffer();}}三、将浮点数转化为字符数组笔者在编制应用程序时有这样的要求:将运算的结果(浮点数)存入eeprom中。我们知道,浮点数在c语言中是以ieee格式存储的,一个浮点数占用四个字节,例如浮点数34.526存为(160,26,10,66)这四个数。要将一个浮点数存入eeprom,实际上就是要存这四个数。那么如何在程序中得到一个浮点数的组成数呢?浮点数在存储时,是存储连续的字节中的,只要设法找到存储位置,就可以得到这些数了。可以定义一个void的指针,将此指针指向需要存储的浮点数,然后将此指针强制转化为char型,这样,利用指针就可以得到组成该浮点数的各个字节的值了。具体程序如下:#define uchar unsigned char#define uint unsigned intvoid ftoc(void){uchar i,*pxuchar x[4]; /*定义字符数组,准备存储浮点数的四个字节*、void *px=x; /*px指针指向数组x*/pf=&a; /*void 型指针指向浮点数首地址*/a=34.526;for(i=0;i&4;i++){ *(px+i)=*((char *)pf+i); /*强制void 型指针转成char型,因为*/} /*void型指针不能运算*/}如果已将数存入eeprom,要将其取出合并,方法也是一样,可参考下面的程序。#define uchar unsigned char#define uint unsigned intvoid ctof(void){uchar i,*pxuchar x[4]={56,180,150,73};void *px=x;pf=&a;for(i=0;i&4;i++){ *((char *)pf+i)=*(px+i);}}以上所用c语言为franklin c51 ver 3.2。
Copyright by ;All rights reserved.C语言是一种计算机程序设计语言_深圳信盈达嵌入式_天涯博客
信盈达集团总部成立于广东省深圳新区龙华民治,下辖深圳信盈达科技有限公司、信盈达IT培训中心、信盈达电子有限公司、信盈达郑州分公司。在深圳开设南山中心、民治中心、沙井中心、龙岗中心、石岩中心等。
今日访问:[$DayVisitCount$]
总访问量:2387
开博时间:
博客排名:293509
(29)(33)(4)
&&&&&&&C语言是一种计算机程序设计语言,它既具有高级语言的特点,又具有汇编语言的特点。它由美国贝尔研究所的D.M.Ritchie于1972年推出,1978年后,C语言已先后被移植到大、中、小及微型机上,它可以作为工作系统设计语言,编写系统应用程序,也可以作为应用程序设计语言,编写不依赖计算机硬件的应用程序。它的应用范围广泛,具备很强的数据处理能力,不仅仅是在软件开发上,而且各类科研都需要用到C语言,适于编写系统软件,三维,二维图形和动画,具体应用比如单片机以及嵌入式系统开发。
1、C是高级语言:它把高级语言的基本结构和语句与低级语言的实用性结合起来。C&语言可以像汇编语言一样对位、字节和地址进行操作,而这三者是计算机最基本的工作单元。[12]
2、C是结构式语言:结构式语言的显著特点是代码及数据的分隔化,即程序的各个部分除了必要的信息交流外彼此独立。这种结构化方式可使程序层次清晰,便于使用、维护以及调试。C&语言是以函数形式提供给用户的,这些函数可方便的调用,并具有多种循环、条件语句控制程序流向,从而使程序完全结构化。[12]
3、C语言功能齐全:具有各种各样的数据类型,并引入了指针概念,可使程序效率更高。而且计算功能、逻辑判断功能也比较强大,可以实现决策目的的游戏。[12]
4、C语言适用范围大:适合于多种操作系统,如Windows、DOS、UNIX等等;也适用于多种机型。C语言对编写需要硬件进行操作的场合,优于其它高级语言,有一些大型应用软件也是用C语言编写的。[12]
5、C语言应用指针:可以直接进行靠近硬件的操作,但是C的指针操作不做保护,也给它带来了很多不安全的因素。C++在这方面做了改进,在保留了指针操作的同时又增强了安全性,受到了一些用户的支持,但是,由于这些改进增加语言的复杂度,也为另一部分所诟病。Java则吸取了C++的教训,取消了指针操作,也取消了C++改进中一些备受争议的地方,在安全性和适合性方面均取得良好的效果,但其本身解释在虚拟机中运行,运行效率低于C++/C。一般而言,C,C++,java被视为同一系的语言,它们长期占据着程序使用榜的前三名。[13]
6、C语言文件由数据序列组成:可以构成二进制文件或文本文件常用的C语言IDE(集成开发环境)有Microsoft&Visual&C++,Dev-C++,Code::Blocks,Borland&C++,Watcom&C++,Borland&C++&Builder,GNU&DJGPP&C++,Lccwin32&C&Compiler&3.1,High&C,Turbo&C,C-Free,win-tc,xcode(mac&os&x)等。[14]
1、对齐处理(Alignment)的标准化(包括_Alignas标志符,alignof运算符,aligned_alloc函数以及&stdalign.h&头文件。
2、_Noreturn&函数标记,类似于&gcc&的&__attribute__((noreturn))。
3、_Generic关键字。
4、多线程(Multithreading)支持,包括:_Thread_local存储类型标识符,&threads.h&;头文件,里面包含了线程的创建和管理函数。
5、增强的Unicode的支持,基于C&Unicode技术报告ISO/IEC&TR&,增强了对Unicode的支持。包括为UTF-16/UTF-32编码增加了char16_t和char32_t数据类型,提供了包含unicode字符串转换函数的头文件&uchar.h&.
6、删除了&gets()&函数,使用一个新的更安全的函数gets_s()替代。
7、增加了边界检查函数接口,定义了新的安全的函数,例如&fopen_s(),strcat_s()&等等。
8、增加了更多浮点处理宏。
9、匿名结构体/联合体支持,这个在gcc早已存在,C11将其引入标准。
10、静态断言(Static&assertions),_Static_assert(),在解释&#if&和&#error&之后被处理。
11、新的&fopen()&模式,(&&x&),类似&POSIX&中的&O_CREAT|O_EXCL,在文件锁中比较常用。
12、新增&quick_exit()&函数作为第三种终止程序的方式。当&exit()失败时可以做最少的清理工作。
13、_Atomic类型修饰符和&stdatomic.h&头文件。
编辑本段优缺点
1、简洁紧凑、灵活方便
C语言一共只有32个关键字,9种控制语句,程序书写形式自由,区分大小写。把高级语言的基本结构和语句与低级语言的实用性结合起来。C&语言可以像汇编语言一样对位、字节和地址进行操作,而这三者是计算机最基本的工作单元。[15]
2、运算符丰富
C语言的运算符包含的范围很广泛,共有34种运算符。C语言把括号、赋值、强制类型转换等都作为运算符处理。从而使C语言的运算类型极其丰富,表达式类型多样化。灵活使用各种运算符可以实现在其它高级语言中难以实现的运算。[15]
3、数据类型丰富
C语言的数据类型有:整型、实型、字符型、数组类型、指针类型、结构体类型、共用体类型等。能用来实现各种复杂的数据结构的运算。并引入了指针概念,使程序效率更高。[16]
4、表达方式灵活实用
C语言提供多种运算符和表达式值的方法,对问题的表达可通过多种途径获得,其程序设计更主动、灵活。它语法限制不太严格,程序设计自由度大,如对整型量与字符型数据及逻辑型数据可以通用等。[17]
5、允许直接访问物理地址,对硬件进行操作
由于C语言允许直接访问物理地址,可以直接对硬件进行操作,因此它既具有高级语言的功能,又具有低级语言的许多功能,能够像汇编语言一样对位(bit)、字节和地址进行操作,而这三者是计算机最基本的工作单元,可用来写系统软件。[18]
6、生成目标代码质量高,程序执行效率高
C语言描述问题比汇编语言迅速,工作量小、可读性好,易于调试、修改和移植,而代码质量与汇编语言相当。C语言一般只比汇编程序生成的目标代码效率低10%~20%。[17]
7、可移植性好
C语言在不同机器上的C编译程序,86%的代码是公共的,所以C语言的编译程序便于移植。在一个环境上用C语言编写的程序,不改动或稍加改动,就可移植到另一个完全不同的环境中运行。[17]
8、表达力强
C语言有丰富的数据结构和运算符。包含了各种数据结构,如整型、数组类型、指针类型和联合类型等,用来实现各种数据结构的运算。C语言的运算符有34种,范围很宽,灵活使用各种运算符可以实现难度极大的运算。
C语言能直接访问硬件的物理地址,能进行位(bit)操作。兼有高级语言和低级语言的许多优点。
它既可用来编写系统软件,又可用来开发应用软件,已成为一种通用程序设计语言。
另外C语言具有强大的图形功能,支持多种显示器和驱动器。且计算功能、逻辑判断功能强大。
1.&C语言的缺点主要表现在数据的封装性上,这一点使得C在数据的安全性上有很大缺陷,这也是C和C++的一大区别。
2.&C语言的语法限制不太严格,对变量的类型约束不严格,影响程序的安全性,对数组下标越界不作检查等。从应用的角度,C语言比其他高级语言较难掌握。也就是说,对用C语言的人,要求对程序设计更熟练一些。[19]
编辑本段语法
C的数据类型包括:整型、字符型、实型或浮点型(单精度和双精度)、枚举类型、数组类型、结构体类型、共用体类型、指针类型和空类型。[20]
常量与变量
常量其值不可改变,符号常量名通常用大写。
变量是以某标识符为名字,其值可以改变的量。标识符是以字母或下划线开头的一串由字母、数字或下划线构成的序列,请注意第一个字符必须为字母或下划线,否则为不合法的变量名。变量在编译时为其分配相应存储单元。
如果一个变量名后面跟着一个有数字的中括号,这个声明就是数组声明。字符串也是一种数组。它们以ASCII的NULL作为数组的结束。要特别注意的是,方括内的索引值是从0算起的。[21]
如果一个变量声明时在前面使用&*&号,表明这是个指针型变量。换句话说,该变量存储一个地址,而&*(此处特指单目运算符&*&,下同。C语言中另有&双目运算符&*)&则是取内容操作符,意思是取这个内存地址里存储的内容。指针是&C&语言区别于其他同时代高级语言的主要特征之一。
指针不仅可以是变量的地址,还可以是数组、数组元素、函数的地址。通过指针作为形式参数可以在函数的调用过程得到一个以上的返回值(不同于return(z)这样的仅能得到一个返回值。
指针是一把双刃剑,许多操作可以通过指针自然的表达,但是不正确的或者过分的使用指针又会给程序带来大量潜在的错误。[21]
C语言的字符串其实就是char型数组,所以使用字符串并不需要引用库。但是C标准库确实包含了一些用于对字符串进行操作的函数,使得它们看起来就像字符串而不是数组。使用这些函数需要引用头文件&string.h&。[22]
文件输入/输出
在C语言中,输入和输出是经由标准库中的一组函数来实现的。在ANSI/ISO&C中,这些函数被定义在头文件&stdio.h&;中。
标准输入/输出
有三个标准输入/输出是标准I/O库预先定义的:
stdin标准输入
stdout标准输出
stderr输入输出错误[20]
C语言的运算非常灵活,功能十分丰富,运算种类远多于其它程序设计语言。在表达式方面较其它程序语言更为简洁,如自加、自减、逗号运算和三目运算使表达式更为简单,但初学者往往会觉的这种表达式难读,关键原因就是对运算符和运算顺序理解不透不全。当多种不同运算组成一个运算表达式,即一个运算式中出现多种运算符时,运算的优先顺序和结合规则显得十分重要。在学习中,对此合理进行分类,找出它们与数学中所学到运算之间的不同点之后,记住这些运算也就不困难了,有些运算符在理解后更会牢记心中,将来用起来得心应手,而有些可暂时放弃不记,等用到时再记不迟。
先要明确运算符按优先级不同分类,《C程序设计》运算符可分为15种优先级,从高到低,优先级为1&~&15,除第2.13级和第14级为从右至左结合外,其它都是从左至右结合,它决定同级运算符的运算顺序。[23]
关键字又称为保留字,就是已被C语言本身使用,不能作其它用途使用的字。例如关键字不能用作变量名、函数名等标识符
由ANSI标准定义的C语言关键字共32个:
auto&double&int&struct&break&else&long&switch
case&enum&register&typedef&char&extern&return&union
const&float&short&unsigned&continue&for&signed&void
default&goto&sizeof&volatile&do&if&while&static&inline
restrict&_Bool&_Complex&_Imaginary&_Generic[24]
一、数据类型关键字
基本数据类型
void:声明函数无返回值或无参数,声明无类型指针,显示丢弃运算结果。
char:字符型类型数据,属于整型数据的一种。
int:整型数据,表示范围通常为编译器指定的内存字节长。
float:单精度浮点型数据,属于浮点数据的一种。
double:双精度浮点型数据,属于浮点数据的一种。
_Bool:布尔型
_Complex:复数的基本类型
_Imaginary:虚数,与复数基本类型相似,没有实部的纯虚数。
_Generic:C11中提供重载的接口入口。
类型修饰关键字
short:修饰int,短整型数据,可省略被修饰的int。
long:修饰int,长整型数据,可省略被修饰的int。
signed:修饰整型数据,有符号数据类型。
unsigned:修饰整型数据,无符号数据类型。
restrict:用于限定和约束指针,并表明指针是访问一个数据对象的唯一且初始的方式。
复杂类型关键字
struct:结构体声明。
union:共用体声明。
enum:枚举声明。
typedef:声明类型别名。
sizeof:得到特定类型或特定类型变量的大小。
inline:内联函数用于取代宏定义,会在任何调用它的地方展开。
存储级别关键字
auto:指定为自动变量,由编译器自动分配及释放。通常在栈上分配。
static:指定为静态变量,分配在静态变量区,修饰函数时,指定函数作用域为文件内部。
register:指定为寄存器变量,建议编译器将变量存储到寄存器中使用,也可以修饰函数形参,建议编译器通过寄存器而不是堆栈传递参数。
extern:指定对应变量为外部变量,即标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。
const:与volatile合称&cv特性&,指定变量不可被当前线程/进程改变(但有可能被系统或其他线程/进程改变)。
volatile:与const合称&cv特性&,指定变量的值有可能会被系统或其他进程/线程改变,强制编译器每次从内存中取得该变量的值。
二、流程控制关键字
return:用在函数体中,返回特定值(如果是void类型,则不返回函数值)。
continue:结束当前循环,开始下一轮循环。
break:跳出当前循环或switch结构。
goto:无条件跳转语句。
if:条件语句,后面不需要放分号。
else:条件语句否定分支(与if连用)。
switch:开关语句(多重分支语句)。
case:开关语句中的分支标记,与switch连用。
default:开关语句中的&其他&分支,可选。
编辑本段循环结构
for循环结构是c语言中最具有特色的循环语句,使用最为灵活方便,它的一般形式为:
for(表达式1;表达式2;表达式3)循环体语句&。(其中;不能省略)
表达式1为初值表达式,用于在循环开始前为循环变量赋初值。
表达式2是循环控制逻辑表达式,它控制循环执行的条件,决定循环的次数。
表达式3为循环控制变量修改表达式,它使for循环趋向结束。
循环控制语句是在循环控制条件成立的情况下被反复执行的语句。
但是在整个for循环过程中,表达式1只计算一次,表达式2和表达式3则可能计算多次,也可能一次也不计算。循环体可能多次执行,也可能一次都不执行。
先执行表达式2,然后执行循环结构,最后表达式3,一直这样循环下去。
for循环语句是c语言种功能最为强大的语句,甚至在一定程度上可以代替其他的循环语句。
do循环结构,do&1&while⑵;的执行顺序是1-&2-&1...循环,2为循环条件。
while循环结构,while⑴&2;&的执行顺序是1-&2-&1...循环,1为循环条件
以上循环语句,当循环条件表达式为真则继续循环,为假则跳出循环。
顺序结构的程序设计是最简单的,只要按照解决问题的顺序写出相应的语句就行,它的执行顺序是自上而下,依次执行。
例如:a&=&3,b&=&5,现交换a,b的值,这个问题就好像交换两个杯子水,这当然要用到第三个杯子,假如第三个杯子是c,那么正确的程序为:c&=&a;&a&=&b;&b&=&c;执行结果是a&=&5,b&=&c&=&3如果改变其顺序,写成:a&=&b;&c&=&a;&b&=c;则执行结果就变成a&=&b&=&c&=&5,不能达到预期的目的,初学者最容易犯这种错误。顺序结构可以独立使用构成一个简单的完整程序,常见的输入、计算,输出三步曲的程序就是顺序结构,例如计算圆的面积,其程序的语句顺序就是输入圆的半径r,计算s&=&3.14159*r*r,输出圆的面积s。不过大多数情况下顺序结构都是作为程序的一部分,与其它结构一起构成一个复杂的程序,例如分支结构中的复合语句、循环结构中的循环体等。[25]
顺序结构的程序虽然能解决计算、输出等问题,但不能做判断再选择。对于要先做判断再选择的问题就要使用选择结构。选择结构的执行是依据一定的条件选择执行路径,而不是严格按照语句出现的物理顺序。选择结构的程序设计方法的关键在于构造合适的分支条件和分析程序流程,根据不同的程序流程选择适当的选择语句。选择结构适合于带有逻辑或关系比较等条件判断的计算,设计这类程序时往往都要先绘制其程序流程图,然后根据程序流程写出源程序,这样做把程序设计分析与语言分开,使得问题简单化,易于理解。程序流程图是根据解题分析所绘制的程序执行流程图。[26]
循环结构可以减少源程序重复书写的工作量,用来描述重复执行某段算法的问题,这是程序设计中最能发挥计算机特长的程序结构,C语言中提供四种循环,即goto循环、while循环、do&while循环和for循环。四种循环可以用来处理同一问题,一般情况下它们可以互相代替换,但一般不提倡用goto循环,因为强制改变程序的顺序经常会给程序的运行带来不可预料的错误。
特别要注意在循环体内应包含趋于结束的语句(即循环变量值的改变),否则就可能成了一个死循环,这是初学者的一个常见错误。
三个循环的异同点:用while和do&while循环时,循环变量的初始化的操作应在循环体之前,而for循环一般在语句1中进行的;while循环和for循环都是先判断表达式,后执行循环体,而do&while循环是先执行循环体后判断表达式,也就是说do&while的循环体最少被执行一次,而while循环和for就可能一次都不执行。另外还要注意的是这三种循环都可以用break语句跳出循环,用continue语句结束本次循环,而goto语句与if构成的循环,是不能用break和&continue语句进行控制的。
顺序结构、分支结构和循环结构并不彼此孤立的,在循环中可以有分支、顺序结构,分支中也可以有循环、顺序结构,其实不管哪种结构,均可广义的把它们看成一个语句。在实际编程过程中常将这三种结构相互结合以实现各种算法,设计出相应程序,但是要编程的问题较大,编写出的程序就往往很长、结构重复多,造成可读性差,难以理解,解决这个问题的方法是将C程序设计成模块化结构。[27]
预编译与条件编译
#define&预编译宏
#if&表达式&#else&if&表达式&#else&#endif&条件编译
#ifdef&宏&#else&#endif&条件编译
#ifndef&宏&#else&#endif&条件编译
模块化程序结构
C语言的模块化程序结构用函数来实现,即将复杂的C程序分为若干模块,每个模块都编写成一个C函数,然后通过主函数调用函数及函数调用函数来实现一大型问题的C程序编写,因此常说:C程序=主函数+子函数。因此,对函数的定义、调用、值的返回等中要尤其注重理解和应用,并通过上机调试加以巩固。更多的技术交流请加恩智浦半导体大中华区产品市场经理陈筠仪表示,恩智浦AC/DC快充解决方案在充...
智能汽车会刊
如今,物联网浪潮已然席卷至汽车电子产业,发动机控制系统、底盘...
虽然5G会成为未来的核心网,而且也是物联网大规模普及的关键技术,但它只是...
第三届·无线通信技术研讨会
2015o第二届中国IoT大会
ETFo智能硬件开发技术培训会
ETFo第三届&消费电子电池管理系统技术论坛
ETFo智能安防技术论坛
成都&智能工业创新应用论坛
移入鼠标可放大二维码
字符串的灵活用法 - 单片机C语言中数组的用法
来源:本站整理
作者:叶子日 11:33
[导读] 以下列出几种字符串的灵活用法,希望能够帮助读者深入了解字符串: #include #include /* ----------------------------------------------------- 此程序用以说明字符串的灵
以下列出几种字符串的灵活用法,希望能够帮助读者深入了解字符串:
-----------------------------------------------------
此程序用以说明字符串的灵活运用
-----------------------------------------------------
-----------------------------------------------------
此函数从字符串s中提取第n个子串,子串间由','分隔
返回指向该子串的指针
-----------------------------------------------------
char *get_sub_string(char *s,unsigned char n)
int d=0;int fore=0;
int len=strlen(s);
if(s[i]==',')
s[i]='\0';
return NULL;
void main()
char string[20];
c=&yahoo&[2]; //c='h'
/*正如前面所述,字符串是由字符串的首地址来表示的,
字符串&yahoo&其实就是它的首地址,那就可以这样来
取其中的某个字符:&yahoo&[2]*/
strcpy(string,&123,234,345,456&);
strcpy(string,get_sub_string(string,2));
(2)二维数组
可由两个下标确定元素的数组就称为二维数组。其定义的一般形式为:
类型说明符&数组名[常量表达式1][常量表达式2]
例如:int array[6][4];
定义了一个二维数组array,有6行4列,共24个元素。
两个方括号中的常量表达1与常量表达式2规定了数组的行数与列数,从而确定了数组中的元素个数。行下标从0开始,最大为5,共6行;列下标也从0开始,最大为3,共4列。数组中共有6X4=24个元素,具体如下表示:
array[0][0]
array[0][1]
array[0][2]
array[0][3]
array[1][0]
array[1][1]
array[1][2]
array[1][3]
array[2][0]
array[2][1]
array[2][2]
array[2][3]
array[3][0]
array[3][1]
array[3][2]
array[3][3]
array[4][0]
array[4][1]
array[4][2]
array[4][3]
array[5][0]
array[5][1]
array[5][2]
array[5][3]
实际使用时,可以把上述二维数组看作一个6行4列的矩阵,是一个平面的二维结构。那么编译程序是如何用一维的存储空间给这样一个二维结构分配连续的存储单元的呢C51采用按行存放的方法,即在内存中先存放第0行元素,再存放第1行、第2行、......元素,每行中先存放第0列,接着存放第1列、第2列、......的元素。
-----------------------------------------------------
此程序用以说明二维数组的使用方法
-----------------------------------------------------
void main()
unsigned char arrays[3][3]={{1,2,3},{2,3,4},{3,4,5}};
//定义一个3行3列的二维数组,其它在内存中还是以一维的方式存储的
//用下面的方式就可以知道这一点
test=((unsigned char *)arrays)[6];//test=3;
//将二维数据的首地址强制转为一维数组,按照一维数组的方式访问它
除了一维数组、二维数组,其实可以定义任何维的数组,多维数组用来表示由多个下标才能决定的量。
例如:int arrays[3][3][3]
表示数组arrays为一个三维数组,对应于三维存储模型。
其实单片机内的存储器是一维的,即所有数据都是依次顺序存储的,所以无论几维数组都由编译程序抽象出数组到单片机存储的实际的一维数组映射。
-----------------------------------------------------
此程序用以说明三维数组
-----------------------------------------------------
void main()
unsigned char arrays[2][2][2]={{{1,2},{2,3}},{{3,4},{4,5}}};
test=arrays[1][1][0];//test=4
test=((unsigned char *)arrays)[7]; //test=5
数组相关文章
数组相关下载
C语言相关文章
C语言相关下载
单片机相关文章
单片机相关下载
技术交流、积极发言! 发表评请遵守相关规定。
IoT将会在未来10年内创造出500亿个联网设备,如何确保这些巨量联网设备的安全性和连接性,正是今天业界面临的2大主要挑战,本文重点将讨论基于ARM的...
一直以来,智能手机上实现4K视频、欣赏AR和VR都是不可能的任务,因为不可能在有限的移动设备功耗预算内,足够长时间地运行高清内容。但是,ARM新推出...
创新实用技术专题
Copyright &
.All Rights Reserved

我要回帖

更多关于 嵌入式与单片机的区别 的文章

 

随机推荐