huaiqiao
发表于 2015-5-29 08:50
顶,吴大哥的原创
jianhong_wu
发表于 2015-5-31 07:50
第二十节:减法运算的5种常见格式。 请先看以下的减法语法格式: “保存变量”=“减数1”-“减数2”-...-“减数N”; 含义是:右边的“减数”与“减数”相减,并且把最终的运算结果赋值给左边的“保存变量”。注意,这里的符号“=”不是等于号的意思,而是赋值的意思。左边的“保存变量”必须是变量,不能是常量,否则编译时会报错。右边的“减数”既可以是变量,也可以是常量,也可以是“保存变量”本身自己。多说一句,何谓变量和常量?变量是可以在程序中被更改的,是被分配的一个RAM空间。常量往往是数字,或者是被分配在ROM空间的一个具体数值。下面根据右边“被减数”与“减数”的不同组合,列出了减法运算的5种常见格式。 第1种:“减数1”是常量,“减数2”是常量。比如:unsigned char a;a=15-3;数字“15”和“3”都是常量。执行上述语句后,保存变量a变成了12。 第2种:“减数1”是变量,“减数2”是常量。比如:unsigned char b;unsigned char x=15;b=x-10;x是变量,“10”是常量。由于原来x变量里面的数值是15,执行上述语句后,保存变量b变成了5。而变量x则保持不变,x还是15。 第3种:“减数1”是变量,“减数2”是变量。比如:unsigned char c;unsigned char x=15;unsigned char y=6;c=x-y;x是变量,y也是变量。由于原来x变量里面的数值是15,y变量里面的数值是6,执行上述语句后,保存变量c变成了9。而变量x和y则保持不变,x还是15,y还是6。 第4种:“减数1”是保存变量本身,“减数2”是常量。比如:unsigned char d=18;d=d-2;d=d-7;d是保存变量,“2”和“7”都是常量。这类语句有一个特点,具备了自减功能,可以更改自己本身自己的数值。比如原来保存变量d的数值是18,执行“d=d-2;”语句后,d变成了16,接着再执行完“d=d-7;”语句后,d最后变成了9。 第5种:“减数1”是保存变量本身,“减数2”是变量。比如:unsigned char e=28;unsigned char x=15;unsigned char y=6;e=e-x;e=e-y;e是保存变量,x与y都是变量。这类语句有一个特点,具备了自减功能,可以更改自己本身自己的数值。比如原来保存变量e的数值是28,执行“e=e-x;”语句后,e变成了13,接着再执行完“e=e-y;”语句后,e最后变成了7。 现在编写一个程序来练习上述5种格式的减法语句,最后把程序编译后下载到坚鸿51学习板观察结果。请直接复制第十节模板程序,修改的main程序代码如下:
void main() //主程序
{
/*---C语言学习区域的开始---------------------------------------------------------------------------*/
unsigned char a; //定义一个变量a,并且分配了1个字节的RAM空间。
unsigned char b; //定义一个变量b,并且分配了1个字节的RAM空间。
unsigned char c; //定义一个变量c,并且分配了1个字节的RAM空间。
unsigned char d=18; //定义一个变量d,并且分配了1个字节的RAM空间。初始化默认为18.
unsigned char e=28; //定义一个变量e,并且分配了1个字节的RAM空间。初始化默认为28.
unsigned char x=15; //定义一个变量x,并且分配了1个字节的RAM空间。初始化默认为15.
unsigned char y=6; //定义一个变量y,并且分配了1个字节的RAM空间。初始化默认为6.
//第1种:“减数1”是常量,“减数2”是常量。
a=15-3;
//第2种:“减数1”是变量,“减数2”是常量。
b=x-10;
//第3种:“减数1”是变量,“减数2”是变量。
c=x-y;
//第4种:“减数1”是保存变量本身,“减数2”是常量。
d=d-2;
d=d-7;
//第5种:“减数1”是保存变量本身,“减数2”是变量。
e=e-x;
e=e-y;
GuiWdData0=a; //把变量a这个数值放到窗口变量0里面显示
GuiWdData1=b; //把变量b这个数值放到窗口变量1里面显示
GuiWdData2=c; //把变量c这个数值放到窗口变量2里面显示
GuiWdData3=d; //把变量d这个数值放到窗口变量3里面显示
GuiWdData4=e; //把变量e这个数值放到窗口变量4里面显示
/*---C语言学习区域的结束---------------------------------------------------------------------------*/
while(1)
{
initial();
key_service();
display_service();
}
}
如何在坚鸿51学习板上观察a,b,c,d,e这5个变量?按下S1或者S5按键即可切换显示不同的窗口,从而显示不同的变量。上坚鸿51学习板观察程序执行的结果如下:变量a为12。变量b为5。变量c为9。变量d为9。变量e为7。 下节预告:减法的连写和自减运算的简写。(未完待续)
huaxiang600
发表于 2015-5-31 15:02
更新快点呗
yuanquan12345
发表于 2015-6-1 16:24
学习。
tony0727
发表于 2015-6-2 20:45
一直在学,一直学不深,有什么建议么,鸿哥
787833238
发表于 2015-6-5 15:22
学习了
jianhong_wu
发表于 2015-6-8 07:51
第二十一节:减法的连写和自减运算的简写。 连减。上一节我列举的减法例子中,右边的减数只有一个。实际上,C语言规则没有限制减数的个数,它的通用格式如下: “保存变量”=“被减数”-“减数1”-“减数2”-...-“减数N”; 被减数与减数的属性。当右边的减数个数总共超过1个的时候,就是我所说的“连减”。被减数和减数的属性没有限定,可以是常量,也可以是变量。比如: a=68-3-15; //被减数和减数全部是常量。 b=q-x-y-k; //被减数和减数全部是变量。 c=63-x-5-k; //被减数和减数,有的是常量,有的是变量。 连减的运行顺序。赋值符号“=”右边的被减数挨个与减数相减,每一次的运算结果都放在一个临时的隐蔽变量里,这个隐蔽的变量我们看不到,是单片机系统内部参与运算时的专用寄存器,当与所有减数相减的计算结果出来后,再把隐蔽变量所保存的计算结果赋值给左边的“保存变量”。 自减。当被减数是“保存变量”本身时,这种情况就是我所说的“自减”。比如:“保存变量”=“保存变量”-“减数1”;“保存变量”=“保存变量”-“减数1”-“减数2”-...-“减数N”; 自减的简写。当被减数是“保存变量”本身,并且只有一个减数时,那么上述自减计算式可以简写成如下格式: “保存变量”-=“减数1”; “保存变量”-=“减数1”-“减数2”-...-“减数N”; 这种格式就是我所说的自减简写。现在举几个例子如下: d-=6;//相当于d=d-6; e-=x;//相当于e=e-x; f-=18-y-k; //相当于f=f-(18-y-k); 自减的特殊简写。在自减运算中,只有一个减数,并且这个减数是常数1时,格式如下: “保存变量”=“保存变量”-1; 这时候,可以把上述格式简写成如下两种格式: “保存变量”--; --“保存变量”; 这两种格式也是俗称的“自减1”操作。比如: g--;//相当于g=g-1或者g-=1; --h;//相当于h=h-1或者h-=1; 自减1符号“--”可以在变量的左边,也可以在变量的右边,它们在这里本质是一样的,没有差别。当然,如果是在循环条件语句中,这时自减1符号“--”在左边还是在右边是有一点点微弱的差别,这方面的内容以后再讲。 上机练习。现在编写一个程序来练习刚才讲到的内容,最后把程序编译后下载到坚鸿51学习板观察结果。请直接复制第十节模板程序,修改的main程序代码如下:
void main() //主程序
{
/*---C语言学习区域的开始---------------------------------------------------------------------------*/
unsigned char a; //定义一个变量a,并且分配了1个字节的RAM空间。
unsigned char b; //定义一个变量b,并且分配了1个字节的RAM空间。
unsigned char c; //定义一个变量c,并且分配了1个字节的RAM空间。
unsigned char d=65; //定义一个变量d,并且分配了1个字节的RAM空间。初始化默认为65.
unsigned char e=38; //定义一个变量e,并且分配了1个字节的RAM空间。初始化默认为38.
unsigned char f=29; //定义一个变量f,并且分配了1个字节的RAM空间。初始化默认为29.
unsigned char g=5; //定义一个变量g,并且分配了1个字节的RAM空间。初始化默认为5.
unsigned char h=5; //定义一个变量h,并且分配了1个字节的RAM空间。初始化默认为5.
unsigned char q=50; //定义一个变量q,并且分配了1个字节的RAM空间。初始化默认为50.
unsigned char x=3; //定义一个变量x,并且分配了1个字节的RAM空间。初始化默认为3.
unsigned char y=6; //定义一个变量y,并且分配了1个字节的RAM空间。初始化默认为6.
unsigned char k=2; //定义一个变量k,并且分配了1个字节的RAM空间。初始化默认为2.
//第1个知识点:连减。
a=68-3-15;//被减数和减数全部是常量。a的结果为:50。
b=q-x-y-k;//被减数和减数全部是变量。b的结果为:39。
c=63-x-5-k;//被减数和减数,有的是常量,有的是变量。c的结果为:53。
//第2个知识点:自减的常规格式。
d-=6;//相当于d=d-6;d的结果为:59。
e-=x;//相当于e=e-x;e的结果为:35。
f-=18-y-k;//相当于f=f-(18-y-k);f的结果为:19。
//第3个知识点:自减的特殊格式。
g--;//相当于g=g-1或者g-=1;g的结果为:4。
--h;//相当于h=h-1或者h-=1;d的结果为:4。
GuiWdData0=a; //把变量a这个数值放到窗口变量0里面显示
GuiWdData1=b; //把变量b这个数值放到窗口变量1里面显示
GuiWdData2=c; //把变量c这个数值放到窗口变量2里面显示
GuiWdData3=d; //把变量d这个数值放到窗口变量3里面显示
GuiWdData4=e; //把变量e这个数值放到窗口变量4里面显示
GuiWdData5=f; //把变量f这个数值放到窗口变量5里面显示
GuiWdData6=g; //把变量g这个数值放到窗口变量6里面显示
GuiWdData7=h; //把变量h这个数值放到窗口变量7里面显示
/*---C语言学习区域的结束---------------------------------------------------------------------------*/
while(1)
{
initial();
key_service();
display_service();
}
}
查看运算结果的方法。如何在坚鸿51学习板上观察a,b,c,d,e,f,g,h这8个变量?按下S1或者S5按键即可切换显示不同的窗口,从而显示不同的变量。上坚鸿51学习板观察程序执行的结果如下: 变量a为50。 变量b为39。 变量c为53。 变量d为59。 变量e为35。 变量f为19。 变量g为4。 变量h为4。 下节预告:减法运算的溢出。(未完待续)
czdo
发表于 2015-6-8 09:03
不错,再支持一下!!!
czdo
发表于 2015-6-8 09:10
写的很不错啊!!楼主有知识啊
ayl439
发表于 2015-6-9 15:38
楼主的**还是很好的~支持一下
ansile
发表于 2015-6-10 13:05
强烈支持
http://www.szsybdz.com
单片机亚
发表于 2015-6-10 22:31
赞~~
aaron96031
发表于 2015-6-12 08:55
LZ很有心,有时间多写写,将来也可以为后来人作为一个借鉴。加油!
jianhong_wu
发表于 2015-6-17 21:49
本帖最后由 jianhong_wu 于 2015-6-17 21:52 编辑
第二十二节:减法运算的溢出。 在开始本章节之前,先纠正一下前面第17节内容的一个小bug。我原文中写道: “保存变量”+=“加数1”+“加数2”+...+“加数N”; 相当于: “保存变量”=“保存变量”+“加数1”+“加数2”+...+“加数N”; 当时我没有考虑到优先级,漏了一个括号,修改后,相当于: “保存变量”=“保存变量”+(“加数1”+“加数2”+...+“加数);这样才算比较准确。同理,我后面所举的例子: f+=18+y+k; //相当于f=f+18+y+k;在注释中也漏了一个括号,应该是: f+=18+y+k; //相当于f=f+(18+y+k); 上述多一个括号或者少一个括号虽然看似不影响运算结果,但是运算顺序是有点不一样的。
现在正式开始讲本节减法溢出的问题。英文“unsigned”的中文意思就是”无符号的”,延伸含义是“无负号无负数”的意思,所以unsigned char ,unsigned int ,unsigned long这三种类型数据都是无负号无负数的,取值只能是0和正数,那么问题来了,当被减数小于减数的时候,运算结果会是什么样子,有什么规律?(1)第一个例子:unsigned char a;
a=0-1;
分析:左边的“保存变量”a的数据长度是1个字节8位,a=0-1可以看成是十六进制的a=0x00-0x01。由于0x00比0x01小,所以假想一下需要向高位借位,借位后成了a=0x100-0x01。所以a的最终结果是0xff(十进制是255)。根据”假想借位”这个规律,如果是b也是unsigned char 类型,那么b=2-5自然就相当于b=0x102-0x05,运算结果b等于0xfd(十进制是253)。(2)第二个例子:unsigned int c;
c=0-1;
分析:左边的“保存变量”c的数据长度是2个字节16位,c=0-1可以看成是十六进制的c=0x0000-0x0001。由于0x0000比0x0001小,所以假想一下需要向高位借位,借位后成了c=0x10000-0x0001。所以c的最终结果是0xffff(十进制是65535)。根据”假想借位”这个规律,如果是d也是unsignedint 类型,那么d=2-5自然就相当于b=0x10002-0x0005,运算结果b等于0xfffd(十进制是65533)。 为了验证上述抛出的”假想借位”,现在编写一个程序来练习刚才讲到的内容,最后把程序编译后下载到坚鸿51学习板观察结果。请直接复制第十节模板程序,修改的main程序代码如下:
void main() //主程序
{
/*---C语言学习区域的开始---------------------------------------------------------------------------*/
unsigned char a; //定义一个变量a,并且分配了1个字节的RAM空间。
unsigned char b; //定义一个变量b,并且分配了1个字节的RAM空间。
unsigned int c; //定义一个变量c,并且分配了2个字节的RAM空间。
unsigned int d; //定义一个变量d,并且分配了2个字节的RAM空间。
//第一个例子,针对a与b都是unsigned char类型数据。
a=0-1;
b=2-5;
//第二个例子,针对c与d都是unsigned int类型的数据。
c=0-1;
d=2-5;
GuiWdData0=a; //把变量a这个数值放到窗口变量0里面显示
GuiWdData1=b; //把变量b这个数值放到窗口变量1里面显示
GuiWdData2=c; //把变量c这个数值放到窗口变量2里面显示
GuiWdData3=d; //把变量d这个数值放到窗口变量3里面显示
/*---C语言学习区域的结束---------------------------------------------------------------------------*/
while(1)
{
initial();
key_service();
display_service();
}
}
查看运算结果的方法。如何在坚鸿51学习板上观察a,b,c,d这4个变量?按下S1或者S5按键即可切换显示不同的窗口,从而显示不同的变量。按下S9按键不松手就可以切换到十六进制的显示界面,松开手后会自动切换到十进制的界面。上坚鸿51学习板观察程序执行的结果如下:
变量a为0xff(十进制是255)。 变量b为0xfd(十进制是253)。 变量c为0xffff(十进制是65535)。 变量d为0xfffd(十进制是65533)。
下节预告:建议减法运算前先把所有变量转换成同一数据类型再参与运算。(未完待续)
yuanquan12345
发表于 2015-6-18 16:38
谢了。
jianhong_wu
发表于 2015-6-21 08:43
第二十三节:建议把所有参与减法运算的变量都转换成unsigned long数据类型。 不管是以前讲的加法,现在讲的减法,还是未来讲的乘法和除法,我都会强烈建议“请把所有参与运算的变量都转成unsigned long类型”。unsigned long变量是三种数据类型中取值范围最大的数,取值范围可达0到4294967295之间,用了此类型变量的运算,不会轻易导致运算溢出的问题。有细心读者会问,万一数据超过了4294967295怎么办?答:可用BCD码的数组方式进行运算。这种数组运算的方法我在《从业将近十年,手把手教你单片机程序框架》里用了好几个章节跟大家介绍过,初学者暂时不用深入学习它。变量转换的方法是引入中间变量,有多少个需要转换的变量就引入多少个中间变量,请看下面这个例子。转换之前:unsigned inta;
unsigned char x=195;
unsigned long y=101;
a=x-y;
分析:上述公式用到3个变量,其中a和x都不是unsigned long变量,因此需要为它们分别引入中间变量t和s。转换之后:unsigned inta;
unsigned char x=195;
unsigned long y=101;
unsigned long t; //引入的中间变量,用来替代a
unsigned long s; //引入的中间变量,用来替代x。
s=0;//s在接收x原数据之前先把高位和低位全部清零。因为s和x的数据宽度不一。
s=x;//接收x原数据,相当于把x转换成unsigned long中间变量。
t=s-y;//此处的t就默认代表了变量a。
本章虽短,但是此方法在实际项目中很重要,大家不可大意。 下节预告:乘法运算的5种常见格式。(未完待续)
xmlovelives
发表于 2015-6-24 20:24
学习
vilan
发表于 2015-6-25 09:38
泛泛之谈
ghl137
发表于 2015-6-26 21:35
准备学习学习
ghl137
发表于 2015-6-26 21:40
jianhong_wu 发表于 2015-2-25 21:01
非常赞同。先学会使用才能进一步研究它的原理。
好主意
页:
1
2
3
4
[5]
6
7
8
9
10
11
12