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
查看完整版本: 从业十年,教你单片机入门基础。(连载)