C语言对比汇编的好处
简单来说,C语言对汇编语言进行了抽象,具有如下优点:
- 更符合人类思维习惯,开发效率高、时间短。
- 模块化。
- 可移植性好。
- 提供数学函数并支持浮点运算。
- 程序可读性和可维护性强。
C语言当然也有缺点,比如实时性通常要比汇编差。在编写汇编的时候可以清楚的知道每一条指令究竟要多少个机器周期,但是在C中掌控准确的时间稍微困难一些。
C51关键字
C51包含ANSI C关键字的同时,也有针对51单片机扩展的一些关键字。C51的扩展关键字从某种程度上体现了C51语言与标准C语言的不同。例如可重入函数、存储模式等等都是标准C中不存在的问题。
ANSI C 关键字
- auto: 自动变量
- double: 双精度类型
- int: 声明整型类型
- struct: 声明结构体类型
- break: 跳出当前循环
- else: 条件语句否定分支(与 if 连用)
- long: 声明长整型类型
- switch :用于开关语句?
- case: 开关语句分支??
- enum: 声明枚举类型
- register: 声明寄存器变量
- typedef: 用以给数据类型取别名(当然还有其他作用)
- char: 声明字符型类型
- extern: 声明变量是在其他文件正声明(也可以看做是引用变量)??
- return: 子程序返回语句(可以带参数,也看不带参数)??
- union: 声明联合数据类型
- const: 声明只读变量
- float: 声明浮点型类型
- short: 声明短整型类型
- unsigned: 声明无符号类型类型
- continue: 结束当前循环,开始下一轮循环?
- for: 一种循环语句(可意会不可言传)
- signed: 生命有符号类型类型
- void: 声明函数无返回值或无参数,声明无类型指针(基本上就这三个作用)
- default: 开关语句中的“其他”分支?
- goto: 无条件跳转语句????
- sizeof: 计算数据类型长度??
- volatile: 说明变量在程序执行中可被隐含地改变?
- do: 循环语句的循环体
- while: 循环语句的循环条件
- static: 声明静态变量
- if: 条件语句
C51扩展关键字
_at_
为变量定义存储空间绝对地址
alien
声明与PL/M51兼容的函数
bdata
可位寻址的内部RAM
bit
位类型
code
ROM
compact
使用外部分页RAM的存储模式
data
直接寻址的内部RAM
idata
间接寻址的内部RAM
interrupt
中断服务函数
large
使用外部RAM的存储模式
pdata
分页寻址的外部RAM
_priority_
RTX51的任务优先级
reentrant
可重入函数
sbit
声明可位寻址的特殊功能位
sfr
8位的特殊功能寄存器
sfr16
16位的特殊功能寄存器
small
内部RAM的存储模式
_task_
实时任务函数
using
选择工作寄存器组
xdata
外部RAM
C51运算符
C51的运算符与C语言几乎无异(至今没有发现区别)。
算术运算符
+
加,?一元取正?
-
减,?一元取负?
*
乘?
/
除
%
取模?
--
自减1?
++
自加1
逻辑运算符
&&
逻辑与
||
逻辑或
!
逻辑非
关系运算符
>
大于
>=
大于等于
<
小于
<=
小于等于
==
等于
!=
不等于?
位运算符号
&
按位与
|
按位或
^
按位异或
-
按位取反
>>
右移
<<
左移
复合运算符
算术运算符与位运算符可以组成符合运算符,例如:+=、-=等等。
其它运算符
?
expr1? expr2:expr3
sizeof
计算字节数
*
指针操作
&
求址
[]
下表运算符
->
成员访问运算符
.
成员访问运算符
C51变量
运算符在C51中与标准的C语言并没有什么差异,但是变量却有一些比较关键的区别。
变量的数据类型
基本变量类型
与标准C语言,C51的基本数据类型有char、int、short、long和float。除float外均可以使用signed和unsigned指定有符号型和无符号型,默认情况下都是signed。char占用一个字节,int和short都占2个字节,long占4个字节,float占4个字节。
其它数据类型
指针类型:指针与标准C中的指针概念相同,指向一个特定的地址(地址存放的可以是变量也可以是函数)。例如:
int func(int a, int b); int (*pointer)(int,int) = func;
其它数据类型:enum、struct、union以及数组。
C51专有数据类型:
bit、sfr、sfr16以及sbit。
bit变量存储在可位寻址区,保存一位二进制数。注:不能用指针指向位变量。
sfr和sfr16指的是特殊寄存器变量。
sbit声明的是可位寻址变量的一个位。可位寻址的变量就是存储在bdata的变量,以及部分sfr。例如:
int bdata bitTest; sbit bit0 = bitTest ^ 0;
例子中的bit0就是bitTest的第0位。
变量的作用域
C51的变量分为局部变量和全局变量。
变量的存储种类
auto:默认
register:编译器尽量将变量放在寄存器中。
extern:全局变量,可以在多个文件中使用。
static:使得局部变量的寿命与程序相同;使得全局变量只在文件内有效。
变量的存储区域
这个是C51与标准C语言区别很明显的地方。C51中可以指定变量存储在具体的存储器区域内:例如片内RAM、片外RAM、或者是ROM里。例如:
char data test = 'c';
定义test变量存储在直接寻址的内部RAM区。具体的存储区域如下表:
存储类型
存储区域
data
片内直接寻址RAM
idata
片内间接寻址RAM
pdata
分页寻址的片外RAM
xdata
片外数据存储(64K)
code
片内统一编址ROM(64K)
bdata
片内可位寻址的RAM(128位)
指针与存储区域
与变量相同,我们也可以指定指针的存储区域,以及指针所指向的变量的存储区域。指明了所指向变量的具体存储区域的指针效率要更高一些,占用的存储区也少一些(三字节一字节)。例如:
char data *str1;//指针指向data存储区的字符变量 char data * data str2;//指针本身也在data区域
绝对地址的变量
在C51中,可以另变量存储在存储器中的特定地址。这是通过“_at_”关键字实现的。例如:
char data test _at_ 0x100;
不过需要注意的是,绝对地址的变量具有如下要求:
- 不能初始化
- bit类型不能用绝对地址
- 只有全局变量才可以使用绝对地址
C51程序结构与函数
顺序结构、选择结构与循环结构
顺序结构仅仅是简单的一个语句一个语句的执行。
选择结构的语句有:if else,switch
循环结构的语句有:for,while,do while
与标准C语言一样,循环结构中可以使用break和continue,switch中可以使用break。
函数
在C51中,函数的声明,定义和调用的方式基本一致,这里仅仅记录一些主要的不同之处:
可重入函数
C51中的函数在默认情况下是不可以被多个进程共享的,而可重入函数则没有这个限制。让函数可重用的方法如下:
int testFunc(int a,int b) reentrant;
指定寄存器组
在C51中,我们可以指定函数指定特定的寄存器组。如果为中断函数指定寄存器组,那么所有被该中断函数调用的函数都必须使用这个寄存器组。
指定函数使用的寄存器组的方法是在函数原型后面加一个using n,n表示寄存器组。
int testFunc(int a,int b) using 0;
中断服务子程序(中断函数)
可以通过在函数原型后面添加interrupt n来指定中断n的中断服务子程序。
int testFunc(int a,int b) interrupt 0;