9第九课 C51运算符和表达式(指针和地址运算符)

合集下载

C51的基本运算

C51的基本运算

C51的基本运算1) C51的算术和赋值运算(1)算术运算符和算术表达式C51语言一共支持5种算术运算符号。

运算符意义说明+加法运算或正值符号-减法运算或负值符号*乘法运算符号/除法运算符号,求整5/2,结果为2%除法运算符号,求余5%2,结果为1在C51语言中把用算术运算符和括号将运算对象连接起来的式子称为算术表达式,运算对象包括常量、变量、函数、数组和结构等。

在算术表达式中需要遵守一定的运算优先级,规定先乘(余),后加减,括号优先级最高,同级别从左到右,规律和数学计算相同。

2)赋值运算符和赋值表达式赋值运算符包括普通赋值运算符和复合赋值运算符两种,普通的赋值运算符使用“=”,复合赋值运算符是在普通赋值运算符之前加上其他运算符所构成的赋值符。

使用赋值运算符连接的变量和表达式构成赋值表达式。

赋值运算表达式举例:a=3*z;a+=b; /*等同于a=a+b*赋值运算涉及变量类型的转换,一般分为两种:一种是自动转换,一种是强制转换。

自动转换:不使用强制类型转化符,而是直接将赋值运算符号右边表达式或变量的值类型转化为左边的类型,一般是从“低字节宽度”向“高字节宽度”转换。

类型说明浮点型和整型浮点类型变量转化为整型时小数点部分被省略,只保留整数部分;反之只把整型修改为浮点型单、双精度浮点型单精度变量转化为双精度时在尾部添0,反之进行四舍五入的截断操作字符型和整型字符型变量转化为整型时,仅仅修改其类型;反之只保留整型的低八位强制转换:使用强制类型转化符来将一种类型转化为另一种类型,强制类型转化符号和变量类型相同。

强制类型转化举例double(y);/*将y转化为double类型*/int(x);z=unsigned char(x+y);/*将double类型数据y和int类型数据x相加之后转化为unsigned char类型赋给z/*1)逻辑运算C51语言有3种逻辑运算符。

①逻辑与:&&。

c51指针用法

c51指针用法

c51指针用法
C51是一种常用的单片机,使用指针可以更灵活地操作内存和外设。

在C51中,指针可以用于访问和操作内存中的数据,也可以用于操作外设寄存器。

首先,我们可以使用指针来访问和操作内存中的数据。

在C51中,内存被分为不同的存储区域,如代码区、数据区和堆栈区。

通过使用指针,我们可以直接访问和修改这些存储区域中的数据。

例如,我们可以使用指针来读取和修改数组中的元素,而不需要使用数组索引。

这种方法可以提高程序的执行效率。

其次,指针还可以用于操作外设寄存器。

在单片机编程中,外设寄存器用于控制和配置外部设备,如GPIO(通用输入输出)、定时器和串口等。

通过使用指针,我们可以直接访问和修改这些寄存器的值,从而控制外部设备的行为。

例如,我们可以使用指针来设置GPIO引脚的状态,或者配置定时器的工作模式。

除了访问和操作内存和外设寄存器,指针还可以用于动态内存分配和数据结构的操作。

在C51中,我们可以使用指针来动态分配内存,并在运行时根据需要分配和释放内存。

这种灵活的内存管理方式可以提高程序的效率和灵活性。

此外,指针还可以用于创建和操作复杂的数据结构,如链表和树等。

通过使用指针,我们可以方便地插入、删除
和修改数据结构中的元素。

总之,C51中的指针用法非常重要,可以帮助我们更灵活地操作内存和外设。

通过使用指针,我们可以提高程序的执行效率,实现动态内存分配,以及创建和操作复杂的数据结构。

因此,熟练掌握C51指针的用法对于单片机编程非常重要。

c语言指针运算符

c语言指针运算符

c语言指针运算符
C语言的指针运算符是一种特殊的运算符,用于处理指针变量的值和地址。

在C语言中,指针变量是一种特殊类型的变量,它可以存储内存地址。

指针运算符包括取地址运算符&和间接寻址运算符*。

取地址运算符&用于获取变量的地址,它的语法格式如下:
&变量名
例如,&num表示获取变量num的地址。

取地址运算符可以用于任何变量,包括基本类型、数组、结构体等。

间接寻址运算符*用于访问指针变量所指向的地址中存储的值,它的语法格式如下:
*指针变量
例如,*ptr表示访问指针变量ptr所指向的地址中存储的值。

间接寻址运算符可以与取地址运算符配合使用,实现对变量地址的读写操作。

指针运算符的使用需要注意指针变量的类型和值。

如果指针变量的类型和指向的数据类型不匹配,会导致类型不安全的行为。

同时,如果指针变量的值没有被初始化或者指向了无效地址,会导致程序崩溃或者产生未定义的行为。

因此,在使用指针运算符时需要格外谨慎。

- 1 -。

c51各进制的符号

c51各进制的符号

C51中支持多种进制,包括二进制、八进制、十进制和十六进制。

在C51中,可以使用前缀来表示不同进制的数。

•二进制数使用前缀"0b"或"b"来表示,例如0b1010或b1010。

•八进制数使用前缀"0"来表示,例如0123或123。

•十进制数没有前缀,直接表示,例如12345。

•十六进制数使用前缀"0x"或"x"来表示,例如0x1a或x1a。

需要注意的是,C51中的整数默认是十进制数,如果需要在代码中明确指定某个数是其他进制的数,就需要使用上述的前缀来表示。

同时,C51中的浮点数默认为十进制数,但也可以使用科学记数法来表示,例如1.23e4表示1.23乘以10的4次方。

c语言运算符和表达式

c语言运算符和表达式

C语言运算符和表达式C语言把除了控制语句和输入输出以外几乎所有的基本操作都作为运算符处理。

1自增(++)、自减(-一)运算符:自增(++)、自减(一)运算符的作用是使变量的值加1或减1,例如,++ii(在使用之前,先使的值加(减)1)i++,i-(在使用i之后,使i的值加(减)1)y++i和i++的不同之处在于:++i是先执行i=i+1,再使用i的值;而i++是先使用i的值,再执行i=i+lβ自增(减)运算符常用于循环语句中,使循环变量自动加1;也用于指针变量,使指针指向下一个地址。

2算术表达式和运算符的优先级与结合性用算术运算符和括号将运算对象连接起来的、符合C语法规则的式子称C 算术表达式。

运算对象包括常量、变量、函数等。

c语言规定了运算符的优先级(如先乘除后加减),还规定了运算符的结合性。

在表达式求值时,先按运算符的优先级别顺序执行,如果在一个运算对象两侧的运算符的优先级别相同,C语言规定了各种运算符的结合方向(结合性),算术运算符的结合方向都是〃自左至右〃,即运算对象先与左面的运算符结合。

算术运算符是自左至右(左结合性),赋值运算符是自右至左(右结合性)。

赋值运算符和赋值表达式赋值运算符就是二,表示〃存储〃,即把赋值号右边表达式的值存给左边的变量。

可以出现在赋值号左边的式子,称为左值(Ieftvalue)o左值必须有内存空间且允许赋值。

常用的左值是变量,但常变量不能作为左值。

赋值运算符的结合性,从右至左。

若有两个赋值号,要先执行右边的。

如:a=b=2相当于是a=(b=2).3不同类型数据间的混合运算在程序中经常会遇到不同类型的数据进行运算,如果一个运算符两侧的看据类型不同,则先自动进行类型转换,使二者成为同一种类型,然后进行运算。

整型、实型,字符型数据间可以进行混合运算。

规律为1)十、-\/运算的两个数中有一个数为float或double型,结果是double 型,因为系统将所有float型数据都先转换为double型,然后进行运算。

c51逻辑运算符

c51逻辑运算符

c51逻辑运算符C51逻辑运算符C51是一种广泛应用于嵌入式系统开发的微控制器。

在C语言中,逻辑运算符是一种用于进行布尔逻辑运算的特殊符号。

C51提供了多种逻辑运算符,包括逻辑与(&&)、逻辑或(||)、逻辑非(!)和逻辑异或(^)。

这些逻辑运算符在嵌入式系统开发中起着至关重要的作用。

逻辑与(&&)是一种用于判断两个条件是否同时满足的运算符。

当两个条件都为真时,逻辑与运算的结果为真;只要有一个条件为假,逻辑与运算的结果就为假。

逻辑与运算符常用于对多个条件进行判断,只有当所有条件都满足时,才会执行相应的操作。

例如,在嵌入式系统中,当传感器检测到温度高于某个阈值且湿度低于某个阈值时,才会启动相应的冷却系统。

逻辑或(||)是一种用于判断两个条件是否至少有一个满足的运算符。

当两个条件中至少有一个为真时,逻辑或运算的结果为真;只有当两个条件都为假时,逻辑或运算的结果才为假。

逻辑或运算符常用于对多个条件进行判断,只要有一个条件满足,就会执行相应的操作。

例如,在嵌入式系统中,当任意一个传感器检测到异常情况时,都需要触发警报系统。

逻辑非(!)是一种用于取反一个条件的运算符。

逻辑非运算符将一个为真的条件变为假,将一个为假的条件变为真。

逻辑非运算符常用于对条件进行取反判断,例如,在嵌入式系统中,当传感器未检测到信号时,需要触发相应的异常处理。

逻辑异或(^)是一种用于判断两个条件是否仅有一个满足的运算符。

当两个条件中仅有一个为真时,逻辑异或运算的结果为真;当两个条件都为真或都为假时,逻辑异或运算的结果为假。

逻辑异或运算符常用于对两个条件进行互斥判断,例如,在嵌入式系统中,当只有一个开关打开时,才会执行相应的操作。

C51逻辑运算符在嵌入式系统开发中发挥着重要的作用。

通过合理地利用逻辑运算符,可以实现复杂的逻辑判断和控制。

在实际应用中,开发者可以根据具体需求选择适当的逻辑运算符,以达到预期的效果。

《C51运算符》课件

《C51运算符》课件

优先级高的运算符先于优先级低的运算符执行。
同一优先级的运算符按照结合性规则执行。
括号可以改变运算符的优先级。
BIG DATA EMPOWERS TO CREATE A NEWERA
算术运算符
总结词
描述加法运算符的功能和用法。
详细描述
加法运算符用于将两个数相加,生成它们的和。在C51中,加法运算符的语法格式为“a + b”,其中a和b是待相加的两个数。
详细描述
位异或运算符(^)的功能是将两个二进制数的每一位进行比较,如果两个相应的位不同,则结果为1,否则为0。例如,如果两个二进制数分别为1010和0101,则按位异或运算的结果为1110。
位左移运算符(<<)的功能是将一个二进制数的所有位向左移动指定的位数。
感谢观看
THANKS
详细描述
BIG DATA EMPOWERS TO CREATE A NEWERA
关系运算符
判断是否大于
大于运算符用于比较两个数值的大小,如果左侧的值大于右侧的值,则结果为真,否则为假。在C51中,大于运算符用">&#小于或等于
要点一
要点二
详细描述
小于等于运算符用于比较两个数值的大小,如果左侧的值小于或等于右侧的值,则结果为真,否则为假。在C51中,小于等于运算符用"<="表示。
《C51运算符》PPT课件
BIG DATA EMPOWERS TO CREATE A NEWERA
目录
CONTENTS
C51运算符概述算术运算符关系运算符逻辑运算符位运算符
BIG DATA EMPOWERS TO CREATE A NEWERA
C51运算符概述

c51逻辑运算符和运算标号

c51逻辑运算符和运算标号

C51逻辑运算符和运算标号
单片机2009-11-28 16:36:50 阅读172 评论0 字号:大中小C51的运算符与C语言几乎无异(至今没有发现区别)。

算术运算符
+ 加, 一元取正
- 减, 一元取负
* 乘
/ 除
% 求余
-- 自减1
++ 自加1
逻辑运算符
&&
逻辑与
|| 逻辑或
! 逻辑非
关系运算符
> 大于
>= 大于等于
< 小于
<= 小于等于
== 等于
!= 不等于
位运算符号
& 按位与
| 按位或
^ 按位异或
~ 按位取反
>> 右移
<< 左移
复合运算符
算术运算符与位运算符可以组成符合运算符,例如:+=、-=. *=. /= 等等。

这里按位与&可以用来定义高地位(与)
temp_h = temp_h & 0xf0; //取高四位temp_l= temp_l & 0x0f; //取低四位
0&0=0; 0&1=0;
1&0=0; 1&1=1;
这里按位或|可以用来合并高地位(或)
P2 = temp_h | temp_l; //设定P2口的值
0| 0=0; 0| 1=1;
1| 0=1; 1| 1=1;。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第3 课我们学习数据类型时,学习过指针类型,知道它是一种存放指向另一个数据的地址的变量类型。

指针是单片机C语言中一个十分重要的概念,也是学习单片机C语言中的一个难点。

对于指针将会在第九课中做详细的讲解。

在这里我们先来了解一下单片机C语言中供给的两个专门用于指针和地址的运算符:
* 取内容
& 取地址取内容和地址的一般形式分别为:
变量 = * 指针变量指针变量 = & 目标变量
取内容运算是将指针变量所指向的目标变量的值赋给左边的变量;取地址运算是将目标变量的地址赋给左边的变量。

要注意的是:指针变量中只能存放地址(也就是指针型数据),一般情况下不要将非指针类型的数据赋值给一个指针变量。

下面来看一个例子,并用一个图表和实例去简单理解指针的使用方法和含义。

设有两个unsigned int 变量 ABC 处CBA 存放在0x0028,0x002A 中另有一个指针变量 portA 存放在0x002C 中那么我们写这样一段程序去看看*,&的运算结果
unsigned int data ABC _at_ 0x0028; unsigned int data CBA _at_ 0x002A; unsigned int data *Port _at_ 0x002C;
#include <at89x51.h>
#include <stdio.h>
void main(void)
{
SCON = 0x50; //串行口方式1,允许接收TMOD = 0x20; //定时器1 定时方式2
TH1 = 0xE8; //11.0592MHz 1200 波特率TL1 = 0xE8;
TI = 1;
TR1 = 1; //启动定时器
ABC = 10; //设初值CBA = 20;
Port = &CBA; //取CBA 的地址放到指针变量Port
*Port = 100; //更改指针变量Port 所指向的地址的内容
printf("1: CBA=%d\n",CBA); //显示此时CBA 的值
Port = &ABC; //取ABC 的地址放到指针变量Port
CBA = *Port; //把当前Port 所指的地址的内容赋给变量CBA printf("2: CBA=%d\n",CBA); //显示此时CBA 的值
printf(" ABC=%d\n",ABC); //显示ABC 的值
}
程序初始时
执行ABC = 10;向ABC 所指的地址0x28H 写入10(0xA),因ABC 是int 类型要占用0x28H 和
0x29H 两个字节的内存空间,低位字节会放入高地址中,所以0x28H 中放入0x00,0x29 H 中放入0x0A
执行CBA = 20;原理和上一句一样
执行Port = &CBA; 取CBA 的首地址放到指针变量Port
*Port = 100; 更改指针变量Port 所指向的地址的内容
其它的语句也是一样的道理,大家能用Keil 的单步执行和打开存储器查看器一看,这样就更不难理解了。

图9-1 存储器查看窗
图9-2 在串行调试窗口的最终结果
sizeof 运算符
看上去这确实是个奇怪的运算符,有点像函数,却又不是。

大家看到size 应该就猜到是和大小有关的吧?是的,sizeof 是用来求数据类型、变量或是表达式的字节数的一个运算符,但它并不像“=”之类运算符那样在程序执行后才能计算出结果,它是直接在编译时产生结果的。

它的语法如下:
sizeof (数据类型)
sizeof (表达式) 下面是两句应用例句,程序大家能试着编写一下。

printf("char 是多少个字节? ½ 字节\n",sizeof(char));
printf("long 是多少个字节? ½ 字节\n",sizeof(long));
结果是:
char 是多少个字节? 1 字节
long 是多少个字节? 4 字节
强制类型转换运算符不知你们是否有自己去试着编一些程序,从中是否有遇到一些问题?开始学习时我就遇到过
这样一个问题:两个不一样数据类型的数在相互赋值时会出现不对的值。

如下面的一段小程序:
void main(void)
{
unsigned char a;
unsigned int b;
b=100*4;
a=b;
while(1);
}
这段小程序并没有什么实际的应用意义,如果你是细心的朋友定会发现a 的值是不会等于
100*4 的。

是的a 和b 一个是char 类型一个是int 类型,从以前的学习可知char 只占一个字节值最大只能是255。

但编译时为何不出错呢?先来看看这程序的运行情况:
图9-3 小程序的运行情况
b=100*4 就能得知b=0x190,这个时候我们能在Watches 查看a 的值,对于watches 窗口我们在第5 课时简单学习过,在这个窗口Locals 页里能查看程序运行中的变量的值,也能
在 watch 页中输入所要查看的变量名对它的值进行查看。

做法是按图中 1 的 watch#1 (或
watch#2),然后光标移到图中的2 按F2 键,这样就能输入变量名了。

在这里我们能查看
到a 的值为0x90,也就是b 的低8 位。

这是因为执行了数据类型的隐式转换。

隐式转换是在程序进行编译时由编译器自动去处理完成的。

所以有必要了解隐式转换的规则:
1.变量赋值时发生的隐式转换,“=”号右边的表达式的数据类型转换成左边变量的数
据类型。

就如上面例子中的把INT 赋值给CHAR 字符型变量,得到的CHAR 将会是I NT 的低8 位。

如把浮点数赋值给整形变量,小数部分将丢失。

2.所有char 型的操作数转换成int 型。

3.两个具有不一样数据类型的操作数用运算符连接时,隐式转换会按以下次序进行:如有一操作数是float 类型,则另一个操作数也会转换成float 类型;如果一个操作数为lon g 类型,另一个也转换成long;如果一个操作数是unsigned 类型,则另一个操作会被转换成unsigned 类型。

从上面的规则能大概知道有那几种数据类型是能进行隐式转换的。

是的,在单片机c语言中只有char,int,long 及float 这几种基本的数据类型能被隐式转换。

而其它的数据类型
就只能用到显示转换。

要使用强制转换运算符应遵循以下的表达形式:
(类型) 表达式用显示类型转换来处理不一样类型的数据间运算和赋值是十分方便和方便的,特别对指针
变量赋值是很有用的。

看一面一段小程序:
#include <at89x51.h>
#include <stdio.h>
void main(void)
{
char xdata * XROM;
char a;
int Aa = 0xFB1C;
long Ba = 0x893B7832;
float Ca = 3.4534;
SCON = 0x50; //串行口方式1,允许接收TMOD = 0x20; //定时器1 定时方式2 TH1 = 0xE8; //11.0592MHz 1200 波特率TL1 = 0xE8;
TI = 1;
TR1 = 1; //启动定时器
XROM=(char xdata *) 0xB012; //给指针变量赋XROM 初值
*XROM = …R‟; //给XROM 指向的绝对地址赋值
a = *((char xdata *) 0xB012); //等同于a = *XROM
printf (“%bx %x %d %c \n”,(char) Aa, (int) Ba,(int)Ca, a);//转换类型并输出while(1);
}
程序运行结果:1c 7832 3 R 在上面这段程序中,能很清楚到到各种类型进行强制类型转换的基本使用方法,程序中先
在外部数据存储器XDATA 中定义了一个字符型指针变量XROM,当用XROM=(char x data *)
0xB012 这一语句时,便把0xB012 这个地址指针赋于了XROM,如你用XROM 则会是非法的,这种方法特别适合于用标识符来存取绝对地址,如在程序前用#define ROM 0x B012 这样的语句,在程序中就能用上面的方法用ROM 对绝对地址0xB012 进行存取操作了。

运算符的优先级说明表格能在笔者的本教程附录中查看。

相关文档
最新文档