int a[] = {1, 2, 3, 4};
// a → &a[0] (型別 int*)
// a + 1 → &a[1] (指標運算:+1 移動 sizeof(int) bytes)
// *a → a[0] (解引用)
// *(a + i) → a[i] (等價關係)
棧區記憶體:
地址: 0x7ffe...10 0x7ffe...14 0x7ffe...18 0x7ffe...1c
值: 1 2 3 4
a[0] a[1] a[2] a[3]
↑
a (陣列名,常量地址,不可修改)
&a[0] (型別 int*)
a + 0
for (int i = 0; i < 4; ++i)
cout << a[i] << ' ';
for (int *p = a; p != a + 4; ++p)
cout << *p << ' '; // p 遞增 sizeof(int) bytes
for (int val : a)
cout << val << ' '; // 編譯器自動轉為指標迴圈
void reverse(int *begin, int *end) { // [begin, end) 左閉右開
--end; // 指向最後一個元素
while (begin < end) {
std::swap(*begin, *end);
++begin; --end;
}
}
int main() {
int a[] = {0,1,2,3,4,5,6,7,8,9};
reverse(a, a + 10); // 傳遞首尾指標
for (int v : a) cout << v << ' '; // 9 8 7 6 5 4 3 2 1 0
}
| 表達式 | 型別 | 值/含義 | 可修改? |
|---|---|---|---|
a | int* (退化) | 首元素地址 | ❌ 陣列名是常量 |
&a | int(*)[4] | 整個陣列地址 | ❌ |
a + 1 | int* | 第二個元素地址 | ✅ 臨時值可賦予指標變數 |
*a | int | 第一個元素值 | ✅ 左值 |
sizeof(a) | size_t | 整個陣列大小 (16 bytes) | — |
sizeof(p) (p=a) | size_t | 指標大小 (4/8 bytes) | — |
void foo(int arr[]); // 等價於
void foo(int *arr); // 等價於
void foo(int arr[10]); // 10 被忽視,仍退化為指標
// 內部無法得知原始陣列長度,必須額外傳遞 size 參數
void foo(int *arr, size_t n);
現代 C++ 應優先用 std::span<T> (C++20) 或 std::vector 保留長度資訊與邊界檢查。
int m[2][3] = {{1,2,3},{4,5,6}};
int (*p)[3] = m; // 指向「含 3 個 int 的陣列」的指標
// m 退化為 int(*)[3],而非 int**
// 訪問:p[1][2] → *(*(p+1)+2) → 6
sizeof、&、alignof 除外)。p + i 自動按 sizeof(*p) 位移,這是陣列高效隨機存取的硬體基礎。std::span/std::vector/std::array 替代裸陣列指標。sizeof 陷阱、正確設計介面的前提。