先說一下字符串字面量(字符串常量):雙引號中的字符和編譯器自動加入末尾的\0字符,都作爲字符串儲存在內存中。字符串常量屬於靜態存儲類別,說明如果在函數中使用字符串常量,該字符串只會儲存一次,在整個程序的生命週期內存在,即使函數被調用多次。用雙引號扣起來的內容被視爲指向該字符串儲存位置的指針。
字符串的賦值可以用指針與數組,請看下面的例子
char str1[] = "I am a student";
const char *str2 = "I am a student too";
以上兩種表示方法還是有一些不同的
先說數組表示法,數組形式str1[]在計算機的內存中分配一個內含15個元素的數組(末尾還要加上空字符'\0'),當程序載入內存時,也載入了程序中的字符串,字符串存儲在靜態存儲區中,但是當程序在開始時纔會爲該數組分配內存,此時纔將字符串拷貝到數組中,注意此時字符串有兩個副本,一個是靜態存儲區中的常量,另一個是存儲在數組中的字符串。str1爲首元素的地址(&str1[0]),是常量地址,不能更改,可以進行str1+1(&str1[1]),但是不允許str++這樣的操作,因爲遞增運算符只能對變量名進行運算。
指針形式(*str2)也使得編譯器爲字符串在靜態存儲區預留19個元素空間,一旦開始執行程序,它會爲指針變量str2流出一個儲存位置,並把字符串的地址儲存在指針變量中,該變量最初指向該字符串的首地址,但它的值可以改變。因此可以使用自增運算符,如++str2將指向第二個字符。
總結一下,初始化數組把靜態存儲區的字符串拷貝到數組中,而初始化指針只把字符串的地址拷貝給指針。
看一下例子
#include <stdio.h>
#define MSG "I'm special"
int main(void) {
char str1[] = MSG;
const char * str2 = MSG;
printf("address of \"I'm special\":%p\n","I'm special");
printf(" address str1:%p\n",str1);
printf(" address str2:%p\n",str2);
printf(" address MSG:%p\n",MSG);
printf("address of \"I'm special\":%p\n","I'm special");
return 0;
}
運行結果爲:
address of "I'm special":0x4006e8
address str1:0x7fff05a39f40
address str2:0x4006e8
address MSG:0x4006e8
address of "I'm special":0x4006e8
str2與MSG的地址相同,而與str1的地址不同。雖然字符串常量"I'm special"在兩個printf()函數中出現了兩次,但是編譯器只使用了一個存儲位置,而且與MSG的地址相同。