基於字元陣列s[]的s,&s

hisun9發表於2024-11-17

看這樣一段程式碼:

#include <iostream>
using namespace std;

int main()
{
    const char s[] = "hello";

    cout << "Array content (s): " << s << endl;       // 輸出字串內容
    cout << "Address of s (&s): " << &s << endl;     // 輸出整個陣列的地址
    cout << "Address of s[0] (s): " << (void*)s << endl; // 強制轉換輸出地址
}

輸出如下:

img

輸出結果解釋

  • Array content (s): hello

    s 被解釋為字串的首地址,因此輸出字串內容。

  • Address of s (&s): 0x70fe10

    &s 是整個陣列的地址,和陣列首地址一致,但型別不同。

  • Address of s[0] (s): 0x70fe10

    s 被轉換為 void*,明確輸出其地址。

著重解釋下為什麼s 被解釋為字串的首地址,因此輸出字串內容

詳細原因與機制

  1. 陣列名的退化

    • 在 C 和 C++ 中,當陣列名 s 在需要指標的上下文中使用時,它會退化為一個指向陣列首元素的指標(即 &s[0])。這種退化適用於大多數場景,例如傳參或與指標運算。

    • 但注意,此時陣列名 s 並不是一個指標,它是一個常量,表示陣列首元素的地址。

  2. cout 的行為

    • cout 是一個流輸出物件,它對不同型別的輸入進行了過載:

    • 如果輸入的是指向 char 的指標(即 const char*char*),cout 會將其解釋為一個 C 風格字串,並輸出字串內容。

    • 如果輸入的是其他型別的指標,例如 void*int*,cout 會輸出這個指標的地址。

    在該程式碼中,s 退化為 const char*,因此 cout 將其解釋為 C 風格字串並輸出 "hello"。

  3. 字串的儲存

const char s[] = "hello"; 實際上在記憶體中分配了一個 6 位元組的陣列:

地址       內容
0x70fe10   'h'
0x70fe11   'e'
0x70fe12   'l'
0x70fe13   'l'
0x70fe14   'o'
0x70fe15   '\0'

當 s 被用作 cout 的引數時,s 退化為 &s[0](即 0x70fe10),因此 cout 會從該地址開始,逐位元組讀取字元並輸出,直到遇到字串的終止符 \0。

著重解釋下s和&s

  1. s 是什麼?

    • s 是一個字元陣列,const char s[] = "hello"; 定義了一個大小為 6(包括字串末尾的空字元 \0)的陣列。

    • s 的型別是 const char[6]。

  2. &s 是什麼?

    • &s 是整個陣列 s 的地址,而不是陣列的第一個元素的地址(s 和 &s 在語義上不同)。

    • s 表示陣列首元素(s[0])的地址,型別是 const char*

    • &s 表示整個陣列的地址,型別是 const char (*)[6]

  3. cout 如何處理 &s?

    • 在 cout 中,標準輸出流沒有過載對 const char (*)[N] 型別的直接處理。

    • 當傳遞 &s 時,它會退化為一個指向陣列的指標。

    • 通常,C++ 的 cout 會將指標解釋為地址,並輸出地址值(例如 0x70fe10)。

相關文章