1. 程式人生 > >C語言自學完備手冊(30)——指標(4)

C語言自學完備手冊(30)——指標(4)

在本篇部落格中介紹字串和指標的密切關係。

字串的兩種實現方式

字串常見的實現方式有如下兩種:

  • 方式1:利用陣列實現字串
  • 方式2:利用指標實現字串

請看如下示例:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    //方式1:利用陣列實現字串
    char str[]="ABC";
    //方式2:利用指標實現字串
    char *ptr="123";
    printf("str=\"%s\",sizeof(str)=%d\n",str,sizeof(str));
    printf("ptr=\"%s\",sizeof(ptr)=%d,sizeof(\"123\")=%d\n",ptr,sizeof(ptr),sizeof("123"));

    return 0;
}

在本示例中用兩種方式實現了字串。

結果如下:

str="ABC",sizeof(str)=4
ptr="123",sizeof(ptr)=4,sizeof("123")=4

圖示如下: 在這裡插入圖片描述

在示例程式碼和圖示之後,我們再來分別深入地學習這兩種字串的實現方式。

利用陣列實現字串

在方式中,str是char[4]型的陣列,各元素從頭開始依次使用’A’、‘B’、‘C’、’\0’進行初始化。在該方式中,陣列str佔用4個位元組的記憶體空間。 既然是陣列,那麼可通過下標的方式訪問元素,例如:

printf("str[0]=%c\n",str[0]);//結果為:str[0]=A

當然也可通過下標修改元素:例如:

str[0]='D';
printf("str[0]=%c\n",str[0]);//結果為:str[0]=D

但是,一定要注意:在該方式中不可以再次為str賦值,例如:str="DEF";,這一點在之前我們也反覆強調過:賦值表示式的左側不可為陣列名! 雖然說左側的陣列名會被解釋為陣列起始元素的地址,但是依然不可以改寫其值。其實,也可以反向思考一下:如果可以賦值,那豈不是就改變了原陣列在記憶體中的地址了?這是不可以的。

利用指標實現字串

在該方式中,ptr是指向char型變數的指標,它的初始值為字串字面量"123"並指向該字面量的第一個字元。從圖示中,我們也可以看出來指標ptr和字串字面量“123”都會佔用記憶體空間(即sizeof(ptr)=4,sizeof("123")=4

)。也就是說:對於同一個字串而言,用指標實現的字串比用陣列實現的字串需要更多的記憶體空間。

既然是陣列,那麼可通過下標的方式訪問元素,例如:

 printf("ptr[0]=%c\n",ptr[0]);//結果為:ptr[0]=1

好嘞,繼續通過下標的方式修改元素,例如:

ptr[0]='9';
printf("ptr[0]=%c\n",ptr[0]);

執行程式碼可以發現:程式不能夠正常執行!這是為什麼呢?在利用指標實現的字串時,該字串常量被定義為只讀;如果試圖通過指標修改這個字串的值程式會出現未定義的異常行為!也就是說:在利用指標實現字串時可通過指標訪問字串字面量中的內容,但是不能通過指標修改字串字面量中的內容!

另外,在利用指標實現字串時指標(例如ptr)不可進行如下宣告:

char *ptr={'1','2','3','\0'};

因為陣列採用的{'1','2','3','\0'}形式的初始值,它不能夠被賦值給單一的變數(例如指標ptr),應該被賦值給arrayName[ ];這點是大家容易犯錯的。

在利用指標實現字串時可以再次為指標(例如指標p)賦值麼?答案是肯定的。例如:

char *p="123";
p="456";

指標p原本指向字串字面量“123”之後被再次賦值,指向了新的字串字面量“456”,此時原來的“123”並不會消失,但變成了無用的記憶體垃圾;圖示如下: 在這裡插入圖片描述