运算符和表达式.docx
- 文档编号:3870720
- 上传时间:2023-05-06
- 格式:DOCX
- 页数:21
- 大小:290.67KB
运算符和表达式.docx
《运算符和表达式.docx》由会员分享,可在线阅读,更多相关《运算符和表达式.docx(21页珍藏版)》请在冰点文库上搜索。
运算符和表达式
运算符和表达式
上课到这一课相隔了好长一段时间,这些日子里收到不少网友的来信支持和鼓励,要求尽快完成余下的部分。
出门在外的人不得不先为吃饭而努力,似乎这也成为我的借口,以后每晚抽空打一些吧这样大家也就可以不用隔太久就能看到一些新东西。
或许我的笔记并不是很正确,但我尽量的保证每课的实验都会亲自做一次,包括硬件的部分,已求不会误人子弟。
随着访问量不断的增加,网站已启用了的国际域名,在这里我感谢各位一直支持磁动力工作室的朋友,更要感激身在远方一直默默支持我的女友。
明浩 2003-7-14晚
呵,费话少说了。
上两课说了常量和变量,先来补充一个用以重新定义数据类型的的语句吧。
这个语句就是typedef,这是个很好用的语句,但我自己却不常用它,通常我定义变量的数据类型时都是使用标准的关键字,这样别人可以很方便的研读你的程序。
如果你是个DELPHI编程爱好者或是程序员,你对变量的定义也许习惯了DELPHI的关键字,如int类型常会用关键字Integer来定义,在用C51时你还想用回这个的话,你可以这样写:
typedefintinteger;
integera,b;
这两句在编译时,其实是先把integer定义为int,在以后的语句中遇到integer就用int置换,integer就等于int,所以a,b也就被定义为int。
typedef不能直接用来定义变量,它只是对已有的数据类型作一个名字上的置换,并不是产生一个新的数据类型。
下面两句就是一个错误的例子:
typedefintinteger;
integer=100;
使用typedef可以有方便程序的移植和简化较长的数据类型定义。
用typedef还可以定义结构类型,这一点在后面详细解说结构类型时再一并说明。
typedef的语法是
typedef已有的数据类型 新的数据类型名
运算符就是完成某种特定运算的符号。
运算符按其表达式中与运算符的关系可分为单目运算符,双目运算符和三目运算符。
单目就是指需要有一个运算对象,双目就要求有两个运算对象,三目则要三个运算对象。
表达式则是由运算及运算对象所组成的具有特定含义的式子。
C是一种表达式语言,表达式后面加";"号就构成了一个表达式语句。
赋值运算符
对于"="这个符号大家不会陌生的,在C中它的功能是给变量赋值,称之为赋值运算符。
它的作用不用多说大家也明白,就是但数据赋给变量。
如,x=10;由此可见利用赋值运算符将一个变量与一个表达式连接起来的式子为赋值表达式,在表达式后面加";"便构成了赋值语句。
使用"="的赋值语句格式如下:
变量=表达式;
示例如下
a=0xFF;//将常数十六进制数FF赋于变量a
b=c=33;//同时赋值给变量b,c
d=e;//将变量e的值赋于变量d
f=a+b;//将变量a+b的值赋于变量f
由上面的例子可以知道赋值语句的意义就是先计算出"="右边的表达式的值,然后将得到的值赋给左边的变量。
而且右边的表达式可以是一个赋值表达式。
在一些朋友的来信中会出现"=="与"="这两个符号混淆的错误原码,问为何编译报错,往往就是错在if(a=x)之类的语句中,错将"="用为"=="。
"=="符号是用来进行相等关系运算。
算术,增减量运算符
对于a+b,a/b这样的表达式大家都很熟悉,用在C语言中,+,/,就是算术运算符。
C51中的算术运算符有如下几个,其中只有取正值和取负值运算符是单目运算符,其它则都是双目运算符:
+ 加或取正值运算符
- 减或取负值运算符
* 乘运算符
/ 除运算符
% 取余运算符
算术表达式的形式:
表达式1 算术运算符 表达式2
如:
a+b*(10-a),(x+9)/(y-a)
除法运算符和一般的算术运算规则有所不同,如是两浮点数相除,其结果为浮点数,如10.0/20.0所得值为0.5,而两个整数相除时,所得值就是整数,如7/3,值为2。
像别的语言一样C的运算符与有优先级和结合性,同样可用用括号"()"来改变优先级。
这些和我们小时候学的数学几乎是一样的,我也不必过多的说明了。
:
( 还有这么多运算符呀!
暂时停一停吧,我们先来做一个实验吧。
学习运算符和另外一些知识时,我们还是给我们的实验板加个串行接口吧。
借助电脑转件直观的看单片机的输出结果,以后我还会用一些简单的实例讲解单片机和PC串口通讯的简单应用和编程。
如果你用的是成品实验板或仿真器,那你就可以跳过这一段了。
在制作电路前我们先来看看要用的MAX232,这里我们不去具体讨论它,只要知道它是TTL和RS232电平相互转换的芯片和基本的引脚接线功能就行了。
通常我会用两个小功率晶体管加少量的电路去替换MAX232,可以省一点,效果也不错(如有兴趣可以查看网站中的相关资料)。
下图就是MAX232的基本接线图。
图7-1 MAX232
在上两课的电路的基础上按图7-3加上MAX232就可以了。
这大热天的拿烙铁焊焊,还真的是热气迫人来呀:
P串口座用DB9的母头,这样就可以用买来的PC串口延长线进行和电脑相连接,也可以直接接到电脑com口上。
图7-2 DB9接头
图7-3 加上了MAX232的实验电路
做好后我们就先用回第一课的"HelloWorld!
"程序,用它来和你的电脑说声Hello!
把程序烧到芯片上,把串口连接好。
嘿嘿,这时要打开你的串口调试软件,没有就赶快到网上DOWN一个了。
你会用Windows的超级中端也行,不过我从不用它。
我用的comdebug,它是个不错的软件,我喜欢它是因为它功能好而且还有"线路状态"功能,这对我制作小玩意时很有用。
串口号,波特率调好,打开串口,单片机上电,就可以在接收区看到不断出现的"HelloWorld!
"。
一定要先打开软件的串口,再把单片机上电,否则可能因字符不对齐而看到乱码哦。
图7-4 调试结果
第七课运算符和表达式
(2)
关系运算符
对于关系运算符,同样我们也并不陌生。
C中有六种关系运算符,这些家伙同样是在小时候学算术时学习过的:
>大于
<小于
>=大于等于
<=小于等于
==等于
!
=等于
或者你是个非C程序员,那么对前四个一定是再熟悉不过的了。
而"=="在VB或PASCAL等中是用"=","!
="则是用"not"。
由于工作关系我自己要使用好几种的程序语言,所以有时也会头晕搞错。
老了咯 :
P
小学时的数学课就教授过运算符是有优先级别的,计算机的语言也不过是人类语言的一种扩展,这里的运算符同样有着优先级别。
前四个具有相同的优先级,后两个也具有相同的优先级,但是前四个的优先级要高于后2个的。
当两个表达式用关系运算符连接起来时,这时就是关系表达式。
关系表达式通常是用来判别某个条件是否满足。
要注意的是用关系运算符的运算结果只有0和1两种,也就是逻辑的真与假,当指定的条件满足时结果为1,不满足时结果为0。
表达式1 关系运算符 表达式2
如:
I<J,I==J,(I=4)>(J=3),J+I>J
借助我们在上一课做好的电路和学习了的相关操作。
我们来做一个关系运算符相关的实例程序。
为了增加学习的趣味性和生动性,不妨我们来假设在做一个会做算术的机器人,当然真正会思考对话的机器,我想我是做不出来的了,这里的程序只是用来学习关系运算符的基本应用。
#include
#include
voidmain(void)
{
intx,y;
SCON=0x50;//串口方式1,允许接收
TMOD=0x20;//定时器1定时方式2
TH1=0xE8;//11.0592MHz1200波特率
TL1=0xE8;
TI=1;
TR1=1;//启动定时器
while
(1)
{
printf("您好!
我叫Robot!
我是一个会做算术的机器人!
\n");//显示
printf("请您输入两个int,X和Y\n");//显示
scanf("%d%d",&x,&y);//输入
if(x printf("X else//当X不小于Y时再作判断 { if(x==y) printf("X=Y\n");//当X等于Y时 else printf("X>Y\n");//当X大于Y时 } } } 要注意的是,在连接PC串口调试时。 发送数字时,发送完一个数字后还要发送一个回车符,以使scanf函数确认有数据输入。 Printf,scanf函数的具体用法,将和其它相关函数集中出现在的C51函数详解中,敬请大家留意。 逻辑运算符 关系运算符所能反映的是两个表达式之间的大小等于关系,那逻辑运算符则是用于求条件式的逻辑值,用逻辑运算符将关系表达式或逻辑量连接起来就是逻辑表达式了。 也许你会对为什? quot;逻辑运算符将关系表达式连接起来就是逻辑表达式了"这一个描述有疑惑的地方。 其实之前说过"要注意的是用关系运算符的运算结果只有0和1两种,也就是逻辑的真与假",换句话说也就是逻辑量,而逻辑运算符就用于对逻辑量运算的表达。 至于复杂的逻辑量的运算法则我也知之甚少,如要了解的朋友可以参看数字电路的教科书、逻辑学或数学书,而之里只能说说简单常用的几种。 逻辑表达式的一般形式为: 逻辑与: 条件式1&&条件式2 逻辑或: 条件式1||条件式2 逻辑非: ! 条件式2 图7-5 演示结果 逻辑与,说白了就是当条件式1"与"条件式2都为真时结果为真(非0值),否则为假(0值)。 也就是说运算会先对条件式1进行判断,如果为真(非0值),则继续对条件式2进行判断,当结果为真时,逻辑运算的结果为真(值为1),如果结果不为真时,逻辑运算的结果为假(0值)。 如果在判断条件式1时就不为真的话,就不用再判断条件式2了,而直接给出运算结果为假。 逻辑或,是指只要二个运算条件中有一个为真时,运算结果就为真,只有当条件式都不为真时,逻辑运算结果才为假。 逻辑非则是把逻辑运算结果值取反,也就是说如果两个条件式的运算值为真,进行逻辑非运算后则结果变为假,条件式运算值为假时最后逻辑结果为真。 同样逻辑运算符也有优先级别,! (逻辑非)→&&(逻辑与)→||(逻辑或),逻辑非的优先值最高。 如有 ! True||False&&True 按逻辑运算的优先级别来分析则得到(True代表真,False代表假) ! True||False&&True False||False&&True//! Ture先运算得False False||False//False&&True运算得False False//最终False||False得False 下面我们来用程序语言去有表达,如下: #include #include voidmain(void) { unsignedcharTrue=1;//定义 unsignedcharFalse=0; SCON=0x50;//串口方式1,允许接收 TMOD=0x20;//定时器1定时方式2 TH1=0xE8;//11.0592MHz1200波特率 TL1=0xE8; TI=1; TR1=1;//启动定时器 if(! True||False&&True) printf("True\n");//当结果为真时 else printf("False\n");//结果为假时 } 大家可以使用以往学习的方法用keil或烧到片子上用串口调试。 可以更改"! True||False&&True"这个条件式,以实验不同算法组合来掌握逻辑运算符的使用方法。 第七课 运算符和表达式(3) 位运算符 学过汇编的朋友都知道汇编对位的处理能力是很强的,但是C语言也能对运算对象进行按位操作,从而使C语言也能具有一定的对硬件直接进行操作的能力。 位运算符的作用是按位对变量进行运算,但是并不改变参与运算的变量的值。 如果要求按位改变变量的值,则要利用相应的赋值运算。 还有就是位运算符是不能用来对浮点型数据进行操作的。 C51中共有6种位运算符。 位运算一般的表达形式如下: 变量1位运算符变量2 位运算符也有优先级,从高到低依次是: "~"(按位取反)→"<<"(左移)→">>"(右移)→"&"(按位与)→"^"(按位异或)→"|"(按位或) 表7-1是位逻辑运算符的真值表,X表示变量1,Y表示变量2 X Y ~X ~Y X&Y X|Y X^Y 0 0 1 1 0 0 0 0 1 1 0 0 1 1 1 0 0 1 0 1 1 1 1 0 0 1 1 0 表7-1 按位取反,与,或和异或的逻辑真值表 利用以前建立起来的实验板,我们来做个实验验证一下位运算是否真是不改变参与变量的值,同时学习位运算的表达形式。 程序很简单,用P1口做运算变量,P1.0-P1.7对应P1变量的最低位到最高位,通过连接在P1口上的LED我们便可以直观看到每个位运算后变量是否有改变或如何改变。 程序如下: #include voidmain(void) { unsignedinta; unsignedintb; unsignedchartemp;//临时变量 P1=0xAA;//点亮D1,D3,D5,D7P1口的二进制为10101010,为0时点亮LED for(a=0;a<1000;a++) for(b=0;b<1000;b++);//延时 temp=P1&0x7;//单纯的写P1|0x7是没有意义的,因为没有变量被影响,不会被编译 //执行P1|0x7后结果存入temp,这时改变的是temp,但P1不会被影响。 //这时LED没有变化,仍然是D1,D3,D5,D7亮 for(a=0;a<1000;a++) for(b=0;b<1000;b++);//延时 P1=0xFF;//熄灭LED for(a=0;a<1000;a++) for(b=0;b<1000;b++);//延时 P1=0xAA;//点亮D1,D3,D5,D7P1口的二进制为10101010,为0时点亮LED for(a=0;a<1000;a++) for(b=0;b<1000;b++);//延时 P1=P1&0x7;//这时LED会变得只有D2灭 //因为之前P1=0xAA=10101010 //与0x7位与0x7=00000111 //结果存入P1P1=00000010//位为O时点亮LED,电路看第三课 for(a=0;a<1000;a++) for(b=0;b<1000;b++);//延时 P1=0xFF;//熄灭LED while (1); //大家可以根据上面的程序去做位或,左移,取反等等。 } 复合赋值运算符 复合赋值运算符就是在赋值运算符"="的前面加上其他运算符。 以下是C语言中的复合赋值运算符: += 加法赋值 >>= 右移位赋值 -= 减法赋值 &= 逻辑与赋值 *= 乘法赋值 |= 逻辑或赋值 /=除法赋值 ^= 逻辑异或赋值 %= 取模赋值 -= 逻辑非赋值 <<=左移位赋值 复合运算的一般形式为: 变量 复合赋值运算符 表达式 其含义就是变量与表达式先进行运算符所要求的运算,再把运算结果赋值给参与运算的变量。 其实这是C语言中一种简化程序的一种方法,凡是二目运算都可以用复合赋值运算符去简化表达。 例如: a+=56等价于a=a+56 y/=x+9等价于y=y/(x+9) 很明显采用复合赋值运算符会降低程序的可读性,但这样却可以使程序代码简单化,并能提高编译的效率。 对于初学C语言的朋友在编程时最好还是根据自己的理解力和习惯去使用程序表达的方式,不要一味追求程序代码的短小。 逗号运算符 如果你有编程的经验,那么对逗号的作用也不会陌生了。 如在VB中"Dima,b,c"的逗号就是把多个变量定义为同一类型的变量,在C也一样,如"inta,b,c",这些例子说明逗号用于分隔表达式用。 但在C语言中逗号还是一种特殊的运算符,也就是逗号运算符,可以用它将两个或多个表达式连接起来,形成逗号表达式。 逗号表达式的一般形式为: 表达式1,表达式2,表达式3……表达式n 这样用逗号运算符组成的表达式在程序运行时,是从左到右计算出各个表达式的值,而整个用逗号运算符组成的表达式的值等于最右边表达式的值,就是"表达式n"的值。 在实际的应用中,大部分情况下,使用逗号表达式的目的只是为了分别得到名个表达式的值,而并不一定要得到和使用整个逗号表达式的值。 要注意的还有,并不是在程序的任何位置出现的逗号,都可以认为是逗号运算符。 如函数中的参数,同类型变量的定义中的逗号只是用来间隔之用而不是逗号运算符。 条件运算符 上面我们说过C语言中有一个三目运算符,它就是"? : "条件运算符,它要求有三个运算对象。 它可以把三个表达式连接构成一个条件表达式。 条件表达式的一般形式如下: 逻辑表达式? 表达式1: 表达式2 条件运算符的作用简单来说就是根据逻辑表达式的值选择使用表达式的值。 当逻辑表达式的值为真时(非0值)时,整个表达式的值为表达式1的值;当逻辑表达式的值为假(值为0)时,整个表达式的值为表达式2的值。 要注意的是条件表达式中逻辑表达式的类型可以与表达式1和表达式2的类型不一样。 下面是一个逻辑表达式的例子。 如有a=1,b=2这时我们要求是取ab两数中的较小的值放入min变量中,也许你会这样写: if(a min=a; else min=b;//这一段的意思是当a 用条件运算符去构成条件表达式就变得简单明了了: min=(a a: b 很明显它的结果和含意都和上面的一段程序是一样的,但是代码却比上一段程序少很多,编译的效率也相对要高,但有着和复合赋值表达式一样的缺点就是可读性相对效差。 在实际应用时根据自己要习惯使用,就我自己来说我喜欢使用较为好读的方式和加上适当的注解,这样可以有助于程序的调试和编写,也便于日后的修改读写。 指针和地址运算符 在第四课我们学习数据类型时,学习过指针类型,知道它是一种存放指向另一个数据的地址的变量类型。 指针是C语言中一个十分重要的概念,也是学习C语言中的一个难点。 对于指针将会在第九课中做详细的讲解。 在这里我们先来了解一下C语言中提供的两个专门用于指针和地址的运算符: * 取内容 & 取地址 取内容和地址的一般形式分别为: 变量=*指针变量 指针变量=&目标变量 取内容运算是将指针变量所指向的目标变量的值赋给左边的变量;取地址运算是将目标变量的地址赋给左边的变量。 要注意的是: 指针变量中只能存放地址(也就是指针型数据),一般情况下不要将非指针类型的数据赋值给一个指针变量。 下面来看一个例子,并用一个图表和实例去简单理解指针的用法和含义。 设有两个unsignedint变量 ABC处CBA存放在0x0028,0x002A中 另有一个指针变量 portA存放在0x002C中 那么我们写这样一段程序去看看*,&的运算结果 unsignedintdataABC_at_0x0028; unsignedintdataCBA_at_0x002A; unsignedintdata*Port_at_0x002C; #include #include voidmain(void) { SCON=0x50;//串口方式1,允许接收 TMOD=0x20;//定时器1定时方式2 TH1=0xE8;//11.0592MHz1200波特率 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的值 } 程序初始时 值 地址 说明 0x00 0x002DH 0x00 0x002CH 0x00 0x002BH 0x00 0x002AH 0x0A 0x0029H 0x00 0x0028H 执行ABC=10;向ABC所指的地址0x28H写入10(0xA),因ABC是int类型要占用0x28H和0x29H两个字节的内存空间,低位字节会放入高地址中,所以0x28H中放入0x00,0x29H中放入0x0A 值 地址 说明 0x00 0x002DH 0x00 0x002CH 0x00 0x002BH 0x00 0x002AH 0x0A 0x0029H ABC为int类型占用两字节 0x00 0x0028H 执行CBA=20;原理和上一句一样 值 地址 说明 0x00 0x002DH 0x00 0x002CH 0x14 0x002BH CBA为int类型占用两字节 0x00 0x002AH 0x0A 0x0029H ABC为int类型占用两字节 0x00 0x0028H 执行Port=&CBA;取CBA的首地址放到指针变量Port 值 地址 说明 0x00 0x002DH 0x2A 0x002CH CBA的首地址存入Port 0x14 0x002BH 0x00 0x002AH 0x0A
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 运算 表达式
![提示](https://static.bingdoc.com/images/bang_tan.gif)