指针与数组在 C++ 中有着密切的关系,理解它们之间的联系和区别对于掌握 C++ 至关重要。

数组名与指针的关系

数组名的本质

#include <iostream>
 
int main() {
    int arr[5] = {10, 20, 30, 40, 50};
    
    // 数组名在大多数情况下会退化为指向第一个元素的指针
    std::cout << "数组名和指针的关系:" << std::endl;
    std::cout << "arr = " << arr << std::endl;           // 数组名
    std::cout << "&arr[0] = " << &arr[0] << std::endl;   // 第一个元素的地址
    std::cout << "arr + 0 = " << (arr + 0) << std::endl; // 指针运算
    
    // 验证它们是否相等
    std::cout << "arr == &arr[0]: " << (arr == &arr[0]) << std::endl;
    
    // 数组名可以像指针一样使用
    std::cout << "*arr = " << *arr << std::endl;         // 解引用得到第一个元素
    std::cout << "*(arr + 1) = " << *(arr + 1) << std::endl; // 第二个元素
    std::cout << "*(arr + 2) = " << *(arr + 2) << std::endl; // 第三个元素
    
    // 数组下标实际上是指针运算的语法糖
    std::cout << "\n数组下标 vs 指针运算:" << std::endl;
    for (int i = 0; i < 5; ++i) {
        std::cout << "arr[" << i << "] = " << arr[i] 
                  << ", *(arr + " << i << ") = " << *(arr + i) << std::endl;
    }
    
    return 0;
}

数组名与指针的区别

#include <iostream>
 
int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    int* ptr = arr;
    
    std::cout << "数组名与指针的区别:" << std::endl;
    
    // 1. sizeof 操作符的区别
    std::cout << "sizeof(arr) = " << sizeof(arr) << std::endl;  // 20 (整个数组)
    std::cout << "sizeof(ptr) = " << sizeof(ptr) << std::endl;  // 8 (指针大小)
    
    // 2. 取地址操作的区别
    std::cout << "&arr = " << &arr << std::endl;       // 整个数组的地址
    std::cout << "&arr[0] = " << &arr[0] << std::endl; // 第一个元素的地址
    std::cout << "&ptr = " << &ptr << std::endl;       // 指针变量的地址
    
    // 3. 类型的区别
    std::cout << "\n类型信息:" << std::endl;
    std::cout << "arr 的类型: int[5]" << std::endl;
    std::cout << "ptr 的类型: int*" << std::endl;
    std::cout << "&arr 的类型: int(*)[5]" << std::endl;
    
    // 4. 赋值操作的区别
    int arr2[5] = {6, 7, 8, 9, 10};
    // arr = arr2;  // 错误!数组名是常量,不能赋值
    ptr = arr2;     // 正确!指针可以重新赋值
    
    std::cout << "重新赋值后 ptr[0] = " << ptr[0] << std::endl;
    
    // 5. 指针运算的区别
    std::cout << "\n指针运算:" << std::endl;
    std::cout << "arr + 1 = " << (arr + 1) << std::endl;
    std::cout << "ptr + 1 = " << (ptr + 1) << std::endl;
    
    // ptr++; // 可以修改指针
    // arr++; // 错误!不能修改数组名
    
    return 0;
}

指针与一维数组

通过指针访问数组

#include <iostream>
 
void printArrayWithPointer(int* arr, int size) {
    std::cout << "使用指针遍历数组:" << std::endl;
    
    // 方法1:下标方式
    std::cout << "方法1 - 下标: ";
    for (int i = 0; i < size; ++i) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;
    
    // 方法2:指针运算
    std::cout << "方法2 - 指针运算: ";
    for (int i = 0; i < size; ++i) {
        std::cout << *(arr + i) << " ";
    }
    std::cout << std::endl;
    
    // 方法3:移动指针
    std::cout << "方法3 - 移动指针: ";
    int* temp = arr;  // 保存原始指针
    for (int i = 0; i < size; ++i) {
        std::cout << *arr << " ";
        arr++;  // 移动指针
    }
    arr = temp;  // 恢复原始指针
    std::cout << std::endl;
}
 
int main() {
    int numbers[6] = {10, 20, 30, 40, 50, 60};
    
    printArrayWithPointer(numbers, 6);
    
    // 指针可以指向数组中的任意位置
    int* ptr = &numbers[2];  // 指向第三个元素
    std::cout << "\n指向数组中间位置:" << std::endl;
    std::cout << "ptr 指向 numbers[2]: " << *ptr << std::endl;
    std::cout << "ptr[-1] = " << ptr[-1] << std::endl;  // 向前访问
    std::cout << "ptr[1] = " << ptr[1] << std::endl;    // 向后访问
    
    // 计算数组边界
    int* begin = numbers;
    int* end = numbers + 6;
    
    std::cout << "\n使用指针范围遍历:" << std::endl;
    for (int* p = begin; p != end; ++p) {
        std::cout << *p << " ";
    }
    std::cout << std::endl;
    
    return 0;
}

动态数组与指针

#include <iostream>
 
class DynamicArray {
private:
    int* data;
    size_t size;
    size_t capacity;
    
public:
    DynamicArray(size_t initial_capacity = 10) 
        : size(0), capacity(initial_capacity) {
        data = new int[capacity];
    }
    
    ~DynamicArray() {
        delete[] data;
    }
    
    void push_back(int value) {
        if (size >= capacity) {
            resize();
        }
        data[size++] = value;
    }
    
    int& operator[](size_t index) {
        return data[index];
    }
    
    const int& operator[](size_t index) const {
        return data[index];
    }
    
    size_t getSize() const { return size; }
    
    void print() const {
        std::cout << "Array: ";
        for (size_t i = 0; i < size; ++i) {
            std::cout << data[i] << " ";
        }
        std::cout << std::endl;
    }
    
private:
    void resize() {
        capacity *= 2;
        int* new_data = new int[capacity];
        
        // 复制旧数据
        for (size_t i = 0; i < size; ++i) {
            new_data[i] = data[i];
        }
        
        delete[] data;
        data = new_data;
        
        std::cout << "Resized to capacity: " << capacity << std::endl;
    }
};
 
int main() {
    DynamicArray arr(3);
    
    // 添加元素
    for (int i = 1; i <= 10; ++i) {
        arr.push_back(i * 10);
        arr.print();
    }
    
    // 访问元素
    std::cout << "\n访问元素:" << std::endl;
    for (size_t i = 0; i < arr.getSize(); ++i) {
        std::cout << "arr[" << i << "] = " << arr[i] << std::endl;
    }
    
    return 0;
}

指针与多维数组

二维数组的指针表示

#include <iostream>
 
int main() {
    // 二维数组
    int matrix[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };
    
    std::cout << "二维数组的内存布局:" << std::endl;
    std::cout << "matrix = " << matrix << std::endl;           // 指向第一行
    std::cout << "matrix[0] = " << matrix[0] << std::endl;     // 第一行的地址
    std::cout << "matrix[1] = " << matrix[1] << std::endl;     // 第二行的地址
    std::cout << "matrix[2] = " << matrix[2] << std::endl;     // 第三行的地址
    
    // 验证行之间的距离
    std::cout << "\n行之间的距离:" << std::endl;
    std::cout << "matrix[1] - matrix[0] = " << (matrix[1] - matrix[0]) << std::endl;
    std::cout << "matrix[2] - matrix[1] = " << (matrix[2] - matrix[1]) << std::endl;
    
    // 不同的访问方式
    std::cout << "\n不同的访问方式:" << std::endl;
    std::cout << "matrix[1][2] = " << matrix[1][2] << std::endl;           // 标准方式
    std::cout << "*(matrix[1] + 2) = " << *(matrix[1] + 2) << std::endl;   // 指针运算
    std::cout << "*(*(matrix + 1) + 2) = " << *(*(matrix + 1) + 2) << std::endl; // 完全指针
    
    // 使用指针遍历二维数组
    std::cout << "\n使用指针遍历二维数组:" << std::endl;
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 4; ++j) {
            std::cout << *(*(matrix + i) + j) << "\t";
        }
        std::cout << std::endl;
    }
    
    // 将二维数组看作一维数组
    int* flat_ptr = &matrix[0][0];  // 指向第一个元素
    std::cout << "\n将二维数组看作一维数组:" << std::endl;
    for (int i = 0; i < 12; ++i) {
        std::cout << flat_ptr[i] << " ";
        if ((i + 1) % 4 == 0) std::cout << std::endl;
    }
    
    return 0;
}

指向数组的指针

#include <iostream>
 
int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    
    // 1. 普通指针:指向数组元素
    int* ptr1 = arr;  // 指向 int
    std::cout << "普通指针:" << std::endl;
    std::cout << "ptr1 = " << ptr1 << std::endl;
    std::cout << "*ptr1 = " << *ptr1 << std::endl;
    std::cout << "ptr1 + 1 = " << (ptr1 + 1) << std::endl;
    
    // 2. 数组指针:指向整个数组
    int (*ptr2)[5] = &arr;  // 指向包含5个int的数组
    std::cout << "\n数组指针:" << std::endl;
    std::cout << "ptr2 = " << ptr2 << std::endl;
    std::cout << "*ptr2 = " << *ptr2 << std::endl;        // 指向数组第一个元素
    std::cout << "ptr2 + 1 = " << (ptr2 + 1) << std::endl; // 跳过整个数组
    
    // 通过数组指针访问元素
    std::cout << "\n通过数组指针访问元素:" << std::endl;
    for (int i = 0; i < 5; ++i) {
        std::cout << "(*ptr2)[" << i << "] = " << (*ptr2)[i] << std::endl;
    }
    
    // 3. 二维数组的数组指针
    int matrix[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };
    
    int (*row_ptr)[4] = matrix;  // 指向包含4个int的数组
    
    std::cout << "\n二维数组的数组指针:" << std::endl;
    for (int i = 0; i < 3; ++i) {
        std::cout << "第 " << i << " 行: ";
        for (int j = 0; j < 4; ++j) {
            std::cout << row_ptr[i][j] << " ";
        }
        std::cout << std::endl;
    }
    
    // 移动数组指针
    std::cout << "\n移动数组指针:" << std::endl;
    row_ptr++;  // 移动到下一行
    std::cout << "移动后的行: ";
    for (int j = 0; j < 4; ++j) {
        std::cout << (*row_ptr)[j] << " ";
    }
    std::cout << std::endl;
    
    return 0;
}

指针数组与数组指针

指针数组

#include <iostream>
#include <cstring>
 
int main() {
    // 1. 整数指针数组
    int a = 10, b = 20, c = 30, d = 40;
    int* int_ptr_array[4] = {&a, &b, &c, &d};
    
    std::cout << "整数指针数组:" << std::endl;
    for (int i = 0; i < 4; ++i) {
        std::cout << "int_ptr_array[" << i << "] = " << int_ptr_array[i]
                  << ", 值 = " << *int