1. 程式人生 > >微控制器C語言之指標變數

微控制器C語言之指標變數

微控制器C語言變數分別有char型,int型,long型,float型等,它們分別佔用記憶體為1個單元,2單元,4單元,4單元等,另外陣列和字串則佔用了記憶體某段連續的單元。這些變數的共同特徵是它們都裝的數值。那如果一個變數裡面裝的不是數值,而是地址,這個變數則稱為指標變數。所以指標變數用於儲存器的地址號。

那麼問題又來了,指標變數佔多大記憶體呢?比如char *p,p指標變數前面用char修飾,莫非佔一個單元?再例如 long *r,r指標變數前用long修飾,莫非是佔4個單元?我們知道C51中,RAM的地址號是從0到255,ROM則是從0到65535。最大的地址號是正整數65535,顯然有兩個位元組便可裝下。因此C51中指標變數自身只佔兩個單元。

既然如此那這些型別修飾符可以不要?我們知道,指標變數中裝的是一個地址,也就是說通過這個地址,我便可以找到這個地址中的資訊。如果指標指向的是一個char型變數,那麼其通過指標(裝載char型變數的地址)我找到了這個變數。但如果是指向一個float型變數呢,如果沒有這個float來修飾指標變數,那麼我們巡著指標只能找到一個位元組的資料,而一個float型有4個位元組,顯然計算機就分不清是不是該把指標後面的三個位元組視為一個完整的資料。所以指標變數前面的型別修飾符不是用於修飾指標變數自身所佔用的地址數量,而是用於修飾指標變數中所儲存的地址與後續地址之間的關聯情況。

接下來我們用一個實驗來感受下指標的用法。

實驗、從單片機發送字串0123456789到桌面串列埠除錯助手。

#include "reg51.h"
#define u16 unsigned int
#define u8 unsigned char

void delay(u16 x)
{
	while(x--);
}

void Uart_Init() //串列埠初始化
{
	SCON=0x50; //8位非同步模式
	TMOD|=0x20;	//定時器1工作方式2
	TH1=253;//9600bit/s
	TR1=1;
}

void Send_Byte(u8 dat)	  //串列埠傳送一個位元組
{
	SBUF=dat; //啟動傳送,只需要把傳送內容給SBUF這個暫存器
	while(TI==0); //等待發送完成,因為TI為1時表示在傳送停止位
	TI=0;
}

 void Send_String(u8 *str)	 //傳送一個字串	*str為字串第一個字元的地址
 {
	while(*str)
	{
		Send_Byte(*str);
		str++;
	}

 }

void main()
{
	Uart_Init();
	while(1)
	{
	   Send_String("0123456789");
	   Send_Byte(10); //回車鍵
	   delay(60000);
	   delay(60000);
	}
}

從模擬串列埠接收器來看,這個程式執行得很好。現在我把void Send_String(u8 *str)修改為void Send_String(u16 *str),重新編譯並模擬,執行得到


13579?跟著一串亂碼,這又是為什麼?u16是一個無符號int型,Send_String函式每次會取兩個單元作為一個數傳進來,進入while迴圈後,第一次就取"0"*256+"1"傳給了Send_Byte函式,而Send_Byte只能裝下u8型即一個單元資料,就就是高位的0要溢位,就只剩下1了。所以一直取到了9,之後因為while(*str),繼續取字串後續的記憶體單元,而這些記憶體單元裡面是什麼並不確定,所以顯示亂碼。

同樣我們可以嘗試void Send_String(long *str)等等。另外補充一個知識點,定義chara; char *p; p=&a; 其中&是C語言求首地址運算子。