您的位置:控制工程论坛网论坛 » 教程与手册 » 第九课 C51运算符和表达式 (指针和地址运算符)

xilinxue

xilinxue   |   当前状态:在线

总积分:16186  2025年可用积分:0

注册时间: 2008-06-26

最后登录时间: 2020-03-22

空间 发短消息加为好友

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

xilinxue  发表于 2009/2/7 18:38:37      857 查看 1 回复  [上一主题]  [下一主题]

手机阅读

    在第 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 的值


}


程序初始时

































地址


说明


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


0x0029H

 

0x00


0x0028H

 

*Port  =  100;  更改指针变量 Port 所指向的地址的内容

































地址


说明


0x00


0x002DH

 

0x2A


0x002CH

 

0x64


0x002BH


Port 指向了 CBA 所在地址 2AH


0x00


0x002AH


并存入 100


0x0A


0x0029H

 

0x00


0x0028H

 

其它的语句也是一样的道理,大家能用 Keil 的单步执行和打开存储器查看器一看,这样


就更不难理解了。




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。但编译时为何不出错呢?先来看看这程序的运行情况:


单片机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  xdata  *)


0xB012 这一语句时,便把 0xB012 这个地址指针赋于了 XROM,如你用 XROM 则会是非法的, 这种方法特别适合于用标识符来存取绝对地址,如在程序前用#define  ROM  0xB012  这样的 语句,在程序中就能用上面的方法用 ROM 对绝对地址 0xB012 进行存取操作了。




1楼 0 0 回复
  • xilinxue

    xilinxue   |   当前状态:在线

    总积分:16186  2025年可用积分:0

    注册时间: 2008-06-26

    最后登录时间: 2020-03-22

    空间 发短消息加为好友

    xilinxue   发表于 2009/2/7 18:38:37

       会使用指针 才算会C 语言,大家一定要认真对待 指针, 
    2楼 回复本楼

    引用 xilinxue 2009/2/7 18:38:37 发表于2楼的内容

总共 , 当前 /