指针与数组

深入理解指针与数组的关系

指针与数组有着密切的关系,理解这种关系对于掌握C语言至关重要。东巴文(db-w.cn) 将带你深入探索指针与数组的内在联系。

💡 东巴文观点:数组名是数组首元素的地址,指针可以像数组一样使用,这是C语言的精髓之一。

指针与一维数组

数组名与指针

#include <stdio.h>

int main() {
    printf("=== 东巴文数组名与指针 ===\n\n");
    
    int arr[] = {10, 20, 30, 40, 50};
    int *ptr = arr;
    
    printf("数组名arr = %p\n", arr);
    printf("指针ptr = %p\n", ptr);
    printf("&arr[0] = %p\n", &arr[0]);
    
    printf("\n三种方式访问数组元素:\n");
    for (int i = 0; i < 5; i++) {
        printf("arr[%d] = %d, *(arr + %d) = %d, *(ptr + %d) = %d\n", 
               i, arr[i], i, *(arr + i), i, *(ptr + i));
    }
    
    return 0;
}

东巴文说明

  • 数组名是数组首元素的地址
  • arr 等价于 &arr[0]
  • arr[i] 等价于 *(arr + i)

指针访问数组

#include <stdio.h>

int main() {
    printf("=== 东巴文指针访问数组 ===\n\n");
    
    int arr[] = {10, 20, 30, 40, 50};
    int *ptr = arr;
    
    // 方式1:数组下标
    printf("方式1 - 数组下标:\n");
    for (int i = 0; i < 5; i++) {
        printf("arr[%d] = %d\n", i, arr[i]);
    }
    
    // 方式2:指针偏移
    printf("\n方式2 - 指针偏移:\n");
    for (int i = 0; i < 5; i++) {
        printf("*(ptr + %d) = %d\n", i, *(ptr + i));
    }
    
    // 方式3:指针自增
    printf("\n方式3 - 指针自增:\n");
    ptr = arr;  // 重置指针
    for (int i = 0; i < 5; i++) {
        printf("*ptr = %d\n", *ptr);
        ptr++;
    }
    
    return 0;
}

数组名与指针的区别

#include <stdio.h>

int main() {
    printf("=== 东巴文数组名与指针的区别 ===\n\n");
    
    int arr[] = {10, 20, 30, 40, 50};
    int *ptr = arr;
    
    printf("sizeof(arr) = %zu 字节\n", sizeof(arr));
    printf("sizeof(ptr) = %zu 字节\n", sizeof(ptr));
    
    // 数组名是常量,不能修改
    // arr = ptr;  // 错误:不能修改数组名
    
    // 指针是变量,可以修改
    ptr++;  // 正确
    printf("\nptr++后:*ptr = %d\n", *ptr);
    
    return 0;
}

东巴文说明

  • 数组名是常量指针,不能修改
  • 指针是变量,可以修改
  • sizeof(数组名) 得到整个数组大小
  • sizeof(指针) 得到指针本身大小

指针与二维数组

二维数组的地址

#include <stdio.h>

int main() {
    printf("=== 东巴文二维数组的地址 ===\n\n");
    
    int matrix[3][3] = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };
    
    printf("二维数组地址:\n");
    printf("matrix = %p\n", matrix);
    printf("matrix[0] = %p\n", matrix[0]);
    printf("&matrix[0][0] = %p\n", &matrix[0][0]);
    
    printf("\n各行地址:\n");
    for (int i = 0; i < 3; i++) {
        printf("matrix[%d] = %p\n", i, matrix[i]);
    }
    
    return 0;
}

东巴文说明

  • matrix 是二维数组名,指向第一行
  • matrix[i] 是第i行的一维数组名
  • matrix[i][j] 是第i行第j列的元素

指向二维数组的指针

#include <stdio.h>

int main() {
    printf("=== 东巴文指向二维数组的指针 ===\n\n");
    
    int matrix[3][3] = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };
    
    // 指向二维数组的指针
    int (*ptr)[3] = matrix;
    
    printf("使用指针访问二维数组:\n");
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", ptr[i][j]);
        }
        printf("\n");
    }
    
    printf("\n使用指针运算访问:\n");
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", *(*(ptr + i) + j));
        }
        printf("\n");
    }
    
    return 0;
}

东巴文说明

  • int (*ptr)[3] - 指向包含3个int元素的一维数组的指针
  • ptr[i][j] 等价于 *(*(ptr + i) + j)
  • ptr + i 指向第i行

指针数组与二维数组

#include <stdio.h>

int main() {
    printf("=== 东巴文指针数组与二维数组 ===\n\n");
    
    int arr1[] = {1, 2, 3};
    int arr2[] = {4, 5, 6};
    int arr3[] = {7, 8, 9};
    
    // 指针数组
    int *ptrArr[3] = {arr1, arr2, arr3};
    
    printf("使用指针数组访问:\n");
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", ptrArr[i][j]);
        }
        printf("\n");
    }
    
    return 0;
}

东巴文说明

  • int *ptr[3] - 指针数组,包含3个int指针
  • int (*ptr)[3] - 指向数组的指针
  • 注意区分这两种声明

指针与数组的应用

数组求和

#include <stdio.h>

int arraySum(int *arr, int size) {
    int sum = 0;
    for (int i = 0; i < size; i++) {
        sum += *(arr + i);
    }
    return sum;
}

int main() {
    printf("=== 东巴文指针实现数组求和 ===\n\n");
    
    int arr[] = {10, 20, 30, 40, 50};
    int size = sizeof(arr) / sizeof(arr[0]);
    
    int sum = arraySum(arr, size);
    
    printf("数组元素:\n");
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n和:%d\n", sum);
    
    return 0;
}

数组查找

#include <stdio.h>

int *findMax(int *arr, int size) {
    int *max = arr;
    for (int i = 1; i < size; i++) {
        if (*(arr + i) > *max) {
            max = arr + i;
        }
    }
    return max;
}

int main() {
    printf("=== 东巴文指针实现数组查找 ===\n\n");
    
    int arr[] = {30, 10, 50, 20, 40};
    int size = sizeof(arr) / sizeof(arr[0]);
    
    int *max = findMax(arr, size);
    
    printf("数组元素:\n");
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n最大值:%d,位置:%ld\n", *max, max - arr);
    
    return 0;
}

数组排序

#include <stdio.h>

void bubbleSort(int *arr, int size) {
    for (int i = 0; i < size - 1; i++) {
        for (int j = 0; j < size - 1 - i; j++) {
            if (*(arr + j) > *(arr + j + 1)) {
                int temp = *(arr + j);
                *(arr + j) = *(arr + j + 1);
                *(arr + j + 1) = temp;
            }
        }
    }
}

int main() {
    printf("=== 东巴文指针实现数组排序 ===\n\n");
    
    int arr[] = {30, 10, 50, 20, 40};
    int size = sizeof(arr) / sizeof(arr[0]);
    
    printf("排序前:\n");
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    
    bubbleSort(arr, size);
    
    printf("排序后:\n");
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    
    return 0;
}

数组复制

#include <stdio.h>

void copyArray(int *dest, int *src, int size) {
    for (int i = 0; i < size; i++) {
        *(dest + i) = *(src + i);
    }
}

int main() {
    printf("=== 东巴文指针实现数组复制 ===\n\n");
    
    int src[] = {10, 20, 30, 40, 50};
    int dest[5];
    int size = sizeof(src) / sizeof(src[0]);
    
    copyArray(dest, src, size);
    
    printf("源数组:\n");
    for (int i = 0; i < size; i++) {
        printf("%d ", src[i]);
    }
    printf("\n");
    
    printf("目标数组:\n");
    for (int i = 0; i < size; i++) {
        printf("%d ", dest[i]);
    }
    printf("\n");
    
    return 0;
}

指针与数组的注意事项

数组越界

#include <stdio.h>

int main() {
    printf("=== 东巴文避免数组越界 ===\n\n");
    
    int arr[] = {10, 20, 30, 40, 50};
    int size = sizeof(arr) / sizeof(arr[0]);
    
    // ✅ 正确:在数组范围内访问
    for (int i = 0; i < size; i++) {
        printf("arr[%d] = %d\n", i, arr[i]);
    }
    
    // ❌ 错误:数组越界
    // printf("%d\n", arr[5]);  // 越界
    // printf("%d\n", *(arr + 5));  // 越界
    
    return 0;
}

指针类型匹配

#include <stdio.h>

int main() {
    printf("=== 东巴文指针类型匹配 ===\n\n");
    
    int arr[] = {10, 20, 30, 40, 50};
    
    // ✅ 正确:类型匹配
    int *intPtr = arr;
    printf("int指针:*intPtr = %d\n", *intPtr);
    
    // ⚠️ 警告:类型不匹配
    // double *dblPtr = (double *)arr;
    // printf("double指针:*dblPtr = %f\n", *dblPtr);
    
    return 0;
}

数组作为函数参数

#include <stdio.h>

// 数组作为参数退化为指针
void printArray(int arr[], int size) {
    printf("sizeof(arr) = %zu (在函数内)\n", sizeof(arr));
    
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

int main() {
    printf("=== 东巴文数组作为函数参数 ===\n\n");
    
    int arr[] = {10, 20, 30, 40, 50};
    int size = sizeof(arr) / sizeof(arr[0]);
    
    printf("sizeof(arr) = %zu (在main中)\n", sizeof(arr));
    
    printArray(arr, size);
    
    return 0;
}

东巴文说明

  • 数组作为函数参数时退化为指针
  • 在函数内 sizeof(arr) 得到指针大小
  • 需要额外传递数组大小

东巴文最佳实践

1. 使用指针传递数组

#include <stdio.h>

// ✅ 推荐:使用指针传递数组
void processArray(int *arr, int size) {
    for (int i = 0; i < size; i++) {
        arr[i] *= 2;
    }
}

int main() {
    printf("=== 东巴文使用指针传递数组 ===\n\n");
    
    int arr[] = {10, 20, 30, 40, 50};
    int size = sizeof(arr) / sizeof(arr[0]);
    
    printf("处理前:\n");
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    
    processArray(arr, size);
    
    printf("处理后:\n");
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    
    return 0;
}

2. 使用const保护数组

#include <stdio.h>

// ✅ 推荐:使用const保护数组不被修改
void printArray(const int *arr, int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    
    // ❌ 错误:不能修改const数组
    // arr[0] = 100;
}

int main() {
    printf("=== 东巴文使用const保护数组 ===\n\n");
    
    int arr[] = {10, 20, 30, 40, 50};
    int size = sizeof(arr) / sizeof(arr[0]);
    
    printArray(arr, size);
    
    return 0;
}

3. 检查数组边界

#include <stdio.h>

int getElement(int *arr, int size, int index) {
    // ✅ 正确:检查数组边界
    if (index >= 0 && index < size) {
        return arr[index];
    }
    return -1;  // 错误值
}

int main() {
    printf("=== 东巴文检查数组边界 ===\n\n");
    
    int arr[] = {10, 20, 30, 40, 50};
    int size = sizeof(arr) / sizeof(arr[0]);
    
    printf("arr[2] = %d\n", getElement(arr, size, 2));
    printf("arr[10] = %d\n", getElement(arr, size, 10));
    
    return 0;
}

东巴文验证清单

完成本章学习后,请确认:

  • 理解指针与一维数组的关系
  • 理解数组名与指针的区别
  • 理解指针与二维数组的关系
  • 掌握指向二维数组的指针
  • 掌握指针与数组的应用
  • 理解指针与数组的注意事项
  • 掌握最佳实践

下一步学习

掌握指针与数组后,你可以继续学习:

如果遇到问题,欢迎访问 东巴文(db-w.cn) 获取帮助!


东巴文(db-w.cn) - 让编程学习更简单

🎯 东巴文指针与数组提示:理解指针与数组的关系是掌握C语言的关键。在 db-w.cn,我们会通过大量实例帮你深入理解指针与数组!