官术网_书友最值得收藏!

1.7 數(shù)組、字符串與指針

本書大量案例使用了數(shù)組定義,例如,下面的數(shù)組DSY_CODE定義了0~9的七段數(shù)碼管段碼表:

        uchar code DSY_CODE[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};

由于在程序運行過程中DSY_CODE的數(shù)據(jù)保持不變,因此,這里將存儲類型設(shè)為code,如果將code改為data也不會影響程序的運行,只是在程序運行時數(shù)組會被分配到數(shù)據(jù)RAM,而不是僅占用程序ROM空間,在Small模式下,省略code相當于將程序存儲類型設(shè)為默認的data類型。

讀者在實際設(shè)計時,如果要將變化的數(shù)組定義在數(shù)據(jù)RAM中,由于data類型僅允許使用128B,如果編譯時提示數(shù)據(jù)RAM空間不夠,可嘗試將data改為idata,例如:

        uchar idata Sort_Result[200];

另外,存儲類型code、data和idata還可以放到數(shù)據(jù)類型前面。

字符串類型也在本書大量案例中使用,例如,下面的字節(jié)串定義:

        char s[20] = "Current Voltage:";
        char s[20] = {"Current Voltage:"};
        char s[20] = {'R','e','s','u','l','t',':'};

這3種定義是完全相同的,它們都占用20B空間,實際串長為16個字符,最后未明確賦值的4B全部為0x00(即'\0'),在液晶屏上顯示這類字符串時,可用以下方法:

     (1)for(i = 0; i < 16; i++){//顯示字符s[i]};
     (2)for(i = 0; i < strlen(s1); i++){//顯示字符s[i]};
     (3)i = 0; while (s[i++]!= '\0') {//顯示字符s[i]};

要注意的是,如果字符串長為16,而字符數(shù)據(jù)空間也只固定給出了16B,那么上述方法中的后兩種就不可靠了,因為最后一個字符后面不一定是字符串結(jié)束標志'\0'。

字符串還可以這樣定義:

        char s[] = "Current Voltage:";
        char *s = "Current Voltage:";

這兩種定義也是相同的,其串長均為16 個字符,所占用的字節(jié)空間均為17B,因為字符串末尾被自動附加了結(jié)束標志字節(jié)0x00(即'\0')。

在已知串長時,上述三種字符串顯示方法均可使用,在字符串長未知時可使用上述方法中的后兩種,另外,上述顯示方法還可以改寫成:

     (1)for(i = 0; i < 16; i++){//顯示字符*(s+i)};
     (2)for(i = 0; i < strlen(s1); i++){//顯示字符*(s+i)};
     (3)i = 0; while (*(s+i)!= '\0') {//顯示字符*(s+i);i++;};

在編寫C語言程序時,除使用字符數(shù)組(字符串)外,還會使用字符串數(shù)組,例如:

        char s[][20] = {"Current Voltage:","Counter:     ","TH:    TL:    "};

如果要在液晶上顯示“Counter:”這個字符串,可用以下語句實現(xiàn):

        for(i = 0; i < strlen(s[1]);i++){//顯示字符s[1][i]};

在英文字符液晶上顯示數(shù)值時需要將待顯示數(shù)據(jù)轉(zhuǎn)換為字符串,這時可用此前提到的數(shù)據(jù)位分解方法,先分解出各位數(shù)字,然后加上0x30(即'0')得到對應(yīng)數(shù)字的ASCII編碼。另一種更為簡單的方法是使用sprintf函數(shù),示例代碼如下:

        char Buf[10];
        float x = -123.45;
        sprintf(Buf , "%5.2f" , x);

上述語句運行后,Buf會被以下字節(jié)填充:

        0x2D,0x31,0x32,0x33,0x2E,0x34,0x35,0x00,0x00,0x00

這些字節(jié)代表字符串"-123.45",該字符串可直接送字符至液晶屏顯示。

如果已經(jīng)有語句:

        char Buf[25] = "Result:           ";
        語句sprintf(Buf + 7 , "%5.2f" , x)會使Buf中的字符串會變?yōu)椋?Result: -123.45"

讀者還可以使用下面的語句得到同樣的結(jié)果:

        char Buf[25];
        sprintf(Buf , "Result:%5.2f" , x) ;

另外,C語言還提供了與字符串有關(guān)的數(shù)據(jù)轉(zhuǎn)換函數(shù)atoi、atol、atof、strtod、strtol、strtoul,讀者在程序設(shè)計中涉及數(shù)據(jù)輸入/輸出及運算與顯示時可以恰當使用這些函數(shù)。

指針是C語言的重要特色之一,對于語句:

        uchar d[10] = {1,2,3,4,5,6,7,8,9,10};
        uchar *pd = d;

pd指向數(shù)組d中的第0個字節(jié),顯示數(shù)組內(nèi)容可使用下面的代碼:

        for(i = 0;i < 10; i++) {//輸出d[i]、*(pd+i)、*pd++ 或 *(d+i)};

但是不能使用下面的代碼:

        for(i = 0;i < 10; i++) {//輸出*d++};

因為數(shù)組名d雖然也是第0個字節(jié)的地址,但它不能在運行過程中改變,也正是因為數(shù)組名同樣也是第0個元素的指針,因此,某些函數(shù)定義中的形參為數(shù)組,調(diào)用函數(shù)時給出的實參常為指向同類型數(shù)據(jù)的指針,反之形參為指針,實參為數(shù)組名也很常見。

前面字符串示例中也出現(xiàn)了指針應(yīng)用,讀者同樣要能熟練運用它們。

由于8051及其派生系列具有獨特結(jié)構(gòu),Keil C51支持以下兩種不同類型的指針。

1)通用指針

上述示例uchar *pd中的pd就是通用指針,指針聲明與標準C語言完全一樣,其特點是總是用3B來存儲指針,第一字節(jié)表示存儲器類型,第二、三字節(jié)分別是指針所指向數(shù)據(jù)地址的高字節(jié)和低字節(jié),這種定義很方便但速度較慢,在所指向的目標空間不明確時普遍使用。

2)存儲器指針

這種指針在定義時指明了存儲器類型,并且指針總是指向特定的存儲器空間(片內(nèi)數(shù)據(jù)RAM、片外數(shù)據(jù)RAM或程序ROM),例如:

        char data *str;
        int xdata *pd;
        ulong code *pul;

由于定義中已經(jīng)指明了存儲器類型,因此,相對于通用指針而言,指針第一字節(jié)省略,對于data、bdata、idata存儲器類型,指針僅需要1B,因為它們的尋址空間都在256B以內(nèi),而code和xdata存儲類型則需要2B指針,因為它們的尋址空間最大為64KB。

使用存儲器指針比使用通用指針效率高,指針所占空間小,速度更快,在存儲器空間明確時,建議使用存儲器指針,如果存儲器空間不明確則使用通用指針。

主站蜘蛛池模板: 遵义市| 五家渠市| 韩城市| 桃江县| 寿光市| 万全县| 淮滨县| 成安县| 阿图什市| 维西| 黔西县| 正安县| 应城市| 湖北省| 鲜城| 和平区| 张家口市| 高青县| 雅安市| 克什克腾旗| 浦北县| 德昌县| 彰武县| 赞皇县| 铜陵市| 思茅市| 黄梅县| 栾城县| 潞西市| 铜川市| 凉城县| 营口市| 肃北| 元阳县| 龙州县| 顺昌县| 克拉玛依市| 曲水县| 潜江市| 囊谦县| 繁峙县|