C语言指针与数组 #

一、数组名与指针 #

1.1 数组名的本质 #

数组名是数组首元素的地址:

c
int arr[5] = {1, 2, 3, 4, 5};

arr 等价于 &arr[0]

c
#include <stdio.h>

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    
    printf("arr = %p\n", (void*)arr);
    printf("&arr[0] = %p\n", (void*)&arr[0]);
    printf("*arr = %d\n", *arr);
    return 0;
}

1.2 数组名与指针的区别 #

c
#include <stdio.h>

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    int* p = arr;
    
    printf("sizeof(arr) = %zu\n", sizeof(arr));
    printf("sizeof(p) = %zu\n", sizeof(p));
    return 0;
}

输出:

text
sizeof(arr) = 20
sizeof(p) = 8

区别:

特性 数组名 指针
本质 地址常量 变量
sizeof 整个数组大小 指针大小
可修改

1.3 &arr 与 arr #

c
#include <stdio.h>

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    
    printf("arr = %p\n", (void*)arr);
    printf("arr+1 = %p\n", (void*)(arr+1));
    printf("&arr = %p\n", (void*)&arr);
    printf("&arr+1 = %p\n", (void*)(&arr+1));
    return 0;
}

输出:

text
arr = 0x7fff5fbff8a0
arr+1 = 0x7fff5fbff8a4
&arr = 0x7fff5fbff8a0
&arr+1 = 0x7fff5fbff8b4
  • arr 类型是 int*,+1 偏移4字节
  • &arr 类型是 int(*)[5],+1 偏移20字节

二、指针遍历数组 #

2.1 基本遍历 #

c
#include <stdio.h>

int main() {
    int arr[5] = {10, 20, 30, 40, 50};
    int* p = arr;
    
    for (int i = 0; i < 5; i++) {
        printf("arr[%d] = %d\n", i, *(p + i));
    }
    return 0;
}

2.2 指针自增遍历 #

c
#include <stdio.h>

int main() {
    int arr[5] = {10, 20, 30, 40, 50};
    int* p = arr;
    
    for (int i = 0; i < 5; i++) {
        printf("%d ", *p++);
    }
    printf("\n");
    return 0;
}

2.3 指针范围遍历 #

c
#include <stdio.h>

int main() {
    int arr[5] = {10, 20, 30, 40, 50};
    int* start = arr;
    int* end = arr + 5;
    
    for (int* p = start; p < end; p++) {
        printf("%d ", *p);
    }
    printf("\n");
    return 0;
}

2.4 修改数组元素 #

c
#include <stdio.h>

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    int* p = arr;
    
    for (int i = 0; i < 5; i++) {
        *p *= 2;
        p++;
    }
    
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}

输出:

text
2 4 6 8 10

三、数组作为函数参数 #

3.1 数组退化为指针 #

c
#include <stdio.h>

void print_array(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() {
    int arr[5] = {1, 2, 3, 4, 5};
    printf("sizeof(arr) = %zu\n", sizeof(arr));
    print_array(arr, 5);
    return 0;
}

输出:

text
sizeof(arr) = 20
sizeof(arr) = 8

数组作为参数时退化为指针。

3.2 等价写法 #

c
void func(int arr[]);
void func(int* arr);

两种写法等价。

3.3 传递数组大小 #

c
#include <stdio.h>

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

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int size = sizeof(arr) / sizeof(arr[0]);
    printf("总和: %d\n", sum(arr, size));
    return 0;
}

3.4 使用指针参数 #

c
#include <stdio.h>

void double_values(int* start, int* end) {
    while (start < end) {
        *start *= 2;
        start++;
    }
}

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int size = sizeof(arr) / sizeof(arr[0]);
    
    double_values(arr, arr + size);
    
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}

四、指针数组 #

4.1 定义 #

指针数组是元素为指针的数组:

c
int* arr[5];

这是一个包含5个 int* 元素的数组。

4.2 使用示例 #

c
#include <stdio.h>

int main() {
    int a = 10, b = 20, c = 30;
    int* arr[3] = {&a, &b, &c};
    
    for (int i = 0; i < 3; i++) {
        printf("arr[%d] = %d\n", i, *arr[i]);
    }
    return 0;
}

4.3 字符串数组 #

c
#include <stdio.h>

int main() {
    const char* names[] = {"Alice", "Bob", "Charlie", "David"};
    int size = sizeof(names) / sizeof(names[0]);
    
    for (int i = 0; i < size; i++) {
        printf("names[%d] = %s\n", i, names[i]);
    }
    return 0;
}

五、数组指针 #

5.1 定义 #

数组指针是指向数组的指针:

c
int (*p)[5];

这是一个指向包含5个int元素数组的指针。

5.2 使用示例 #

c
#include <stdio.h>

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    int (*p)[5] = &arr;
    
    for (int i = 0; i < 5; i++) {
        printf("%d ", (*p)[i]);
    }
    printf("\n");
    return 0;
}

5.3 指针数组 vs 数组指针 #

c
int* arr[5];
int (*p)[5];
类型 含义
int* arr[5] 包含5个int指针的数组
int (*p)[5] 指向包含5个int数组的指针

5.4 记忆方法 #

  • [] 优先级高于 *
  • int* arr[5]:arr先与[]结合,是数组
  • int (*p)[5]:p先与*结合,是指针

六、多维数组与指针 #

6.1 二维数组 #

c
int arr[3][4] = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
};

6.2 理解二维数组 #

text
arr[i][j] 等价于 *(*(arr + i) + j)
c
#include <stdio.h>

int main() {
    int arr[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };
    
    printf("arr = %p\n", (void*)arr);
    printf("arr[0] = %p\n", (void*)arr[0]);
    printf("&arr[0][0] = %p\n", (void*)&arr[0][0]);
    
    printf("arr[1] = %p\n", (void*)arr[1]);
    printf("arr[1] - arr[0] = %ld\n", arr[1] - arr[0]);
    return 0;
}

6.3 指针遍历二维数组 #

c
#include <stdio.h>

int main() {
    int arr[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };
    
    int* p = &arr[0][0];
    int total = 3 * 4;
    
    for (int i = 0; i < total; i++) {
        printf("%d ", *p++);
    }
    printf("\n");
    return 0;
}

6.4 行指针 #

c
#include <stdio.h>

int main() {
    int arr[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };
    
    int (*p)[4] = arr;
    
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 4; j++) {
            printf("%2d ", p[i][j]);
        }
        printf("\n");
    }
    return 0;
}

七、实战应用 #

7.1 动态数组 #

c
#include <stdio.h>
#include <stdlib.h>

int main() {
    int size = 5;
    int* arr = (int*)malloc(size * sizeof(int));
    
    if (arr == NULL) {
        return 1;
    }
    
    for (int i = 0; i < size; i++) {
        arr[i] = i + 1;
    }
    
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    
    free(arr);
    return 0;
}

7.2 字符串处理 #

c
#include <stdio.h>

int main() {
    const char* fruits[] = {"Apple", "Banana", "Cherry"};
    int size = sizeof(fruits) / sizeof(fruits[0]);
    
    for (int i = 0; i < size; i++) {
        printf("%s\n", fruits[i]);
    }
    return 0;
}

7.3 矩阵操作 #

c
#include <stdio.h>

void print_matrix(int (*mat)[4], int rows) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < 4; j++) {
            printf("%2d ", mat[i][j]);
        }
        printf("\n");
    }
}

int main() {
    int matrix[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };
    
    print_matrix(matrix, 3);
    return 0;
}

八、总结 #

数组名与指针 #

概念 说明
arr 首元素地址
&arr 整个数组地址
arr[i] *(arr + i)
&arr[i] arr + i

指针数组 vs 数组指针 #

类型 定义 用途
指针数组 int* arr[5] 存储多个指针
数组指针 int (*p)[5] 指向数组

多维数组 #

c
arr[i][j] ≡ *(*(arr + i) + j)

函数参数 #

数组作为参数退化为指针,需要传递大小。

下一步,让我们学习指针与函数!

最后更新:2026-03-26