(玩電子) 電子技術學習與研究
當前位置:單片機教程網 >> 基礎教程 >> 瀏覽文章

第九課 C51運算符和表達式(指針和地址運算符)

作者:佚名   來源:本站原創   點擊數:x  更新時間:2007年07月15日   【字體:

在第 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 的單步執行和打開存儲器查看器一看,這樣

就更不難理解了。

圖 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 將會是 INT 的低 8 位。如把浮點數賦值給整形變量,小數部分將丟失。

2.所有 char 型的操作數轉換成 int 型。

3.兩個具有不一樣數據類型的操作數用運算符連接時,隱式轉換會按以下次序進行:如 有一操作數是 float 類型,則另一個操作數也會轉換成 float 類型;如果一個操作數為 long 類型,另一個也轉換成 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  xdata  *)

0xB012 這一語句時,便把 0xB012 這個地址指針賦于了 XROM,如你用 XROM 則會是非法的, 這種方法特別適合于用標識符來存取絕對地址,如在程序前用#define  ROM  0xB012  這樣的 語句,在程序中就能用上面的方法用 ROM 對絕對地址 0xB012 進行存取操作了。運算符的優先級說明表格能在筆者的 本教程附錄 中查看。

發表評論】【告訴好友】【收藏此文】【關閉窗口

文章評論

相關文章

qq群北京赛车机器人
ssp即时赔率 江西时时彩 基金理财平台大全 中国股票指数一览 新快3 江苏11选5网上购 大透乐是什么时候开奖 7mnba篮球比分直播 炒股的人容易得什么病 女皇之心 n0934东京热 天海翼在线视频教师 武汉按摩地方 丘咲爱米莉作品番号 河北十一选五app 新上海麻将对对碰