C語言:指針和數組

const char * p = "Hello World!";
const char Array[] = "Hello World!";

以上兩種聲明,p和Array都使用了字符串“Hello World!”的地址。在這種情況下,帶雙引號的字符串本身決定了預留給字符串的存儲空間,但這兩種形式並不是完全相同的。

數組形式和指針形式有何不同呢?
**數組形式(Array[])**在計算機的內存中分配一個內含13個字節的數組,該數組中每個元素被初始化爲字符串字面量對應的值。通常,字符串“Hello World!”都作爲可執行文件的的一部分存儲在數據段中(靜態存儲區)。當程序運行時,纔會爲數組Array[]分配內存,此時纔會把字符串從數據段拷貝到數組,即Array[]中的值爲原始字符串的一個副本,而原始字符串依舊原封不動地保存在數據段。並且Array被編譯器識別爲備份字符串的首地址別名,爲地址常量不可更改,即++Array之類的操作都是錯誤的。

**指針形式(p)**與數組形式不一樣,從定義開始,指針p就保存着原始字符串“Hello World!”的首地址,並且指針p的值是可以改變的,即++p操作是合法的,表示指向下一個字符‘e’。

總之,初始化數組是把靜態存儲區的字符串拷貝到數組中,而初始化指針只是把字符串的地址拷貝給指針。
——————————————————————————————

#include <stdio.h>

#define MSG "I love China."
int main(int argc, char const *argv[])
{
    const char *p = MSG;
    char Array[] = MSG;
    printf("adddress of \"I love China.\": %p\n", "I love China");
    printf("           address of Array: %p\n", Array);
    printf("               address of p: %p\n", p);
    printf("             address of MSG: %p\n", MSG);
    printf("adddress of \"I love China.\": %p\n", "I love China");
    return 0;
}

輸出結果:

adddress of "I love China.": 0x7f22cc200826
           address of Array: 0x7fffcac294ca
               address of p: 0x7f22cc200818
             address of MSG: 0x7f22cc200818
adddress of "I love China.": 0x7f22cc200826

從程序輸出的數據可以看出:

  1. p與MSG的地址是相同的,而Array的地址是不同的,所以是符合上面的結論的;
  2. 兩次printf函數打印的“I love China.”的地址是一樣的,說明兩次在字符串都存儲在同一個位置,但是卻與MSG的位置不同,說明編譯器編譯的時候可以把多次使用的相同的字面量的字符串存儲在一處或多處

對於沒有使用const限定符的指針初始化,能否使用該指針來修改這個字符串呢?

char * word = "big";
word[0] = 'p';      // 是否允許呢?

編譯器可能是允許這樣做,但是對於標準C此行爲是未定義的。因爲word指針的初始化是將字符串“big”的首地址賦值給word,而字符串“big”還是存儲在數據段中,並沒有備份到其他位置(與上述Array[]數組初始化方式區別),而根據上述歷程,編譯器有可能使用內存中的一個副本來表示完全相同的字符串字面量,所以直接使用指針修改了字符串有可能會直接影響到所有使用到該字符串的代碼。因此,建議把指針初始化爲字符串字面變量時使用const限定符。如下:

const char * word = "big";
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章