> 技术文档 > 指针数组与数组指针的区别

指针数组与数组指针的区别

#include int main(){ // 1. 指针数组 (Array of Pointers) // 指针数组是一个数组,其元素都是指针。 int a = 100, b = 200, c = 300, d = 400; int *arr_of_ptrs[4] = {&a, &b, &c, &d}; printf(\"------------指针数组示例:------------\\n\"); for (int i = 0; i < 4; i++) { printf(\"arr_of_ptrs[%d] = %p, *arr_of_ptrs[%d] = %d\\n\",  i, (void *)arr_of_ptrs[i], i, *arr_of_ptrs[i]); } // 2. 数组指针 (Pointer to Array) // 数组指针是一个指针,它指向整个数组。 int arr[4] = {10, 20, 30, 40}; // 声明一个数组指针:指向包含4个整数的数组 int (*arr_ptr)[4] = &arr; printf(\"\\n------------数组指针示例:------------\\n\"); printf(\"arr_ptr地址: %p\\n\", (void *)arr_ptr); printf(\"arr地址: %p\\n\", (void *)arr); // 通过数组指针访问数组元素 printf(\"第一个元素: %d\\n\", (*arr_ptr)[0]); printf(\"第二个元素: %d\\n\", (*arr_ptr)[1]); // 指针算术:移动整个数组的大小 printf(\"arr_ptr + 1地址: %p (前进%d字节)\\n\", (void *)(arr_ptr + 1), (int)((char *)(arr_ptr + 1) - (char *)arr_ptr)); return 0;}

int (*p_array)[4] = &arr;int *p = arr; 的区别

这两种指针声明方式在C语言中有本质的区别,主要体现在指针类型、语义和指针算术运算上。

代码示例

#include int main() { int arr[4] = {10, 20, 30, 40}; // 方式1: 指向数组第一个元素的指针 int *p = arr; // 方式2: 指向整个数组的指针 int (*p_array)[4] = &arr; printf(\"数组地址: %p\\n\", (void *)arr); printf(\"&arr地址: %p\\n\", (void *)&arr); printf(\"\\nint *p = arr:\\n\"); printf(\"p地址: %p, 值: %d\\n\", (void *)p, *p); printf(\"p+1地址: %p, 值: %d\\n\", (void *)(p+1), *(p+1)); printf(\"\\nint (*p_array)[4] = &arr:\\n\"); printf(\"p_array地址: %p\\n\", (void *)p_array); printf(\"(*p_array)[0] = %d\\n\", (*p_array)[0]); printf(\"p_array+1地址: %p\\n\", (void *)(p_array+1)); return 0;}

主要区别

1. 指针类型不同

  • int *p = arr;:

    • p 是指向整型的指针(int*
    • 指向数组的第一个元素
  • int (*p_array)[4] = &arr;:

    • p_array 是指向包含4个整数的数组的指针(int(*)[4]
    • 指向整个数组

2. 指针算术运算不同

  • int *p = arr;:

    • p + 1 前进一个 int 的大小(通常4字节)
    • 指向数组的下一个元素
  • int (*p_array)[4] = &arr;:

    • p_array + 1 前进整个数组的大小(4 × sizeof(int) = 16字节)
    • 指向下一个相同大小的数组

3. 解引用方式不同

  • int *p = arr;:

    • *p 直接得到数组的第一个元素的值
    • p[i]*(p+i) 访问数组的第i个元素
  • int (*p_array)[4] = &arr;:

    • *p_array 得到整个数组(类型为 int[4]
    • (*p_array)[i] 访问数组的第i个元素

内存布局示意图

内存地址: 0x1000 0x1004 0x1008 0x100C值: 10 20 30 40 ↑ ↑ p p+1  ↑ p_array (指向整个数组)  ↑ p_array+1 (指向下一个数组,地址0x1010)

实际应用场景

使用 int *p = arr;(常见用法)

// 遍历数组元素int arr[4] = {10, 20, 30, 40};int *p = arr;for (int i = 0; i < 4; i++) { printf(\"%d \", *(p + i)); // 或 printf(\"%d \", p[i]);}

使用 int (*p_array)[4] = &arr;(特殊用法)

// 处理二维数组int matrix[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};// 指向二维数组的指针int (*p_matrix)[4] = matrix;for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { printf(\"%d \", p_matrix[i][j]); // 或 printf(\"%d \", (*(p_matrix + i))[j]); } printf(\"\\n\");}

类型兼容性

需要注意的是,虽然 arr&arr 的值相同(都指向数组的起始地址),但它们的类型不同:

  • arr 的类型是 int[4],在大多数表达式中退化为 int*
  • &arr 的类型是 int(*)[4]

因此,以下赋值需要类型转换:

int arr[4] = {10, 20, 30, 40};int *p1 = arr; // 正确,类型兼容int *p2 = (int *)&arr; // 需要显式类型转换

总结

  • int *p = arr; 创建了一个指向数组第一个元素的指针,适用于大多数数组操作
  • int (*p_array)[4] = &arr; 创建了一个指向整个数组的指针,主要用于处理多维数组
  • 两种指针的值相同(指向同一地址),但类型不同,导致指针算术运算的行为不同
  • 理解这一区别有助于编写更准确和高效的C代码,特别是在处理多维数组时