C语言指针运算 #

一、指针运算概述 #

1.1 支持的运算 #

指针支持以下运算:

运算 示例
加整数 p + n
减整数 p - n
指针相减 p2 - p1
比较 p1 < p2
自增自减 p++, p–

1.2 运算单位 #

指针运算以类型大小为单位:

c
int* p;
p + 1;

p + 1 实际偏移 sizeof(int) 字节(通常4字节)。

二、指针加减整数 #

2.1 基本运算 #

c
#include <stdio.h>

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

输出:

text
p = 0x7fff5fbff8a0, *p = 10
p+1 = 0x7fff5fbff8a4, *(p+1) = 20
p+2 = 0x7fff5fbff8a8, *(p+2) = 30

2.2 不同类型指针 #

c
#include <stdio.h>

int main() {
    char arr[5] = {'A', 'B', 'C', 'D', 'E'};
    char* p = arr;
    
    printf("p = %p, *p = %c\n", (void*)p, *p);
    printf("p+1 = %p, *(p+1) = %c\n", (void*)(p+1), *(p+1));
    
    int arr2[5] = {1, 2, 3, 4, 5};
    int* q = arr2;
    
    printf("q = %p, *q = %d\n", (void*)q, *q);
    printf("q+1 = %p, *(q+1) = %d\n", (void*)(q+1), *(q+1));
    return 0;
}

2.3 指针减整数 #

c
#include <stdio.h>

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

2.4 运算原理 #

c
p + n 实际地址 = p的地址 + n * sizeof(类型)
p - n 实际地址 = p的地址 - n * sizeof(类型)

三、指针自增自减 #

3.1 前置与后置 #

c
#include <stdio.h>

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

输出:

text
*p++ = 10
*p = 20
*++p = 30
*p = 30

3.2 运算优先级 #

表达式 等价于 说明
*p++ *(p++) 先取值,后移动
(*p)++ (*p)++ 先取值,值加1
*++p *(++p) 先移动,后取值
++*p ++(*p) 值加1

3.3 示例 #

c
#include <stdio.h>

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

输出:

text
初始: *p = 10
(*p)++后: *p = 11
++*p后: *p = 12

四、指针相减 #

4.1 计算元素个数 #

c
#include <stdio.h>

int main() {
    int arr[10] = {0};
    int* p1 = arr;
    int* p2 = arr + 5;
    
    printf("p2 - p1 = %ld\n", p2 - p1);
    return 0;
}

输出:

text
p2 - p1 = 5

4.2 计算数组长度 #

c
#include <stdio.h>

int main() {
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int* start = arr;
    int* end = arr + sizeof(arr) / sizeof(arr[0]);
    
    int length = end - start;
    printf("数组长度: %d\n", length);
    return 0;
}

4.3 注意事项 #

指针相减要求两个指针指向同一数组:

c
int arr1[5], arr2[5];
int* p1 = arr1;
int* p2 = arr2;
printf("%ld\n", p2 - p1);

五、指针比较 #

5.1 比较运算符 #

c
#include <stdio.h>

int main() {
    int arr[5] = {10, 20, 30, 40, 50};
    int* p1 = arr;
    int* p2 = arr + 4;
    
    printf("p1 < p2: %d\n", p1 < p2);
    printf("p1 > p2: %d\n", p1 > p2);
    printf("p1 == p2: %d\n", p1 == p2);
    printf("p1 != p2: %d\n", p1 != p2);
    return 0;
}

5.2 遍历数组 #

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;
}

5.3 查找元素 #

c
#include <stdio.h>

int* find(int* start, int* end, int value) {
    while (start < end) {
        if (*start == value) {
            return start;
        }
        start++;
    }
    return NULL;
}

int main() {
    int arr[] = {10, 20, 30, 40, 50};
    int* result = find(arr, arr + 5, 30);
    
    if (result != NULL) {
        printf("找到: %d, 索引: %ld\n", *result, result - arr);
    } else {
        printf("未找到\n");
    }
    return 0;
}

六、指针与下标 #

6.1 等价关系 #

c
arr[i]  等价于  *(arr + i)
&arr[i] 等价于  arr + i

6.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("arr[%d] = %d\n", i, arr[i]);
        printf("*(arr+%d) = %d\n", i, *(arr + i));
        printf("p[%d] = %d\n", i, p[i]);
        printf("*(p+%d) = %d\n", i, *(p + i));
        printf("---\n");
    }
    return 0;
}

6.3 负下标 #

c
#include <stdio.h>

int main() {
    int arr[5] = {10, 20, 30, 40, 50};
    int* p = &arr[2];
    
    printf("p[-2] = %d\n", p[-2]);
    printf("p[-1] = %d\n", p[-1]);
    printf("p[0] = %d\n", p[0]);
    printf("p[1] = %d\n", p[1]);
    return 0;
}

输出:

text
p[-2] = 10
p[-1] = 20
p[0] = 30
p[1] = 40

七、指针运算应用 #

7.1 字符串长度 #

c
#include <stdio.h>

size_t my_strlen(const char* str) {
    const char* p = str;
    while (*p) {
        p++;
    }
    return p - str;
}

int main() {
    printf("长度: %zu\n", my_strlen("Hello"));
    return 0;
}

7.2 字符串复制 #

c
#include <stdio.h>

char* my_strcpy(char* dest, const char* src) {
    char* p = dest;
    while ((*p++ = *src++) != '\0') {
    }
    return dest;
}

int main() {
    char dest[20];
    my_strcpy(dest, "Hello, World!");
    printf("%s\n", dest);
    return 0;
}

7.3 数组求和 #

c
#include <stdio.h>

int sum(int* start, int* end) {
    int total = 0;
    while (start < end) {
        total += *start++;
    }
    return total;
}

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

7.4 数组反转 #

c
#include <stdio.h>

void reverse(int* start, int* end) {
    end--;
    while (start < end) {
        int temp = *start;
        *start = *end;
        *end = temp;
        start++;
        end--;
    }
}

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

八、指针运算注意事项 #

8.1 越界访问 #

c
int arr[5] = {1, 2, 3, 4, 5};
int* p = arr;
printf("%d\n", *(p + 10));

越界访问导致未定义行为。

8.2 未定义行为 #

c
int arr[5] = {1, 2, 3, 4, 5};
int* p = &arr[0];
int* q = &arr[5];
printf("%ld\n", q - p);
printf("%ld\n", p - q);

可以指向数组末尾,但不能解引用。

8.3 不同数组指针运算 #

c
int arr1[5], arr2[5];
int* p1 = arr1;
int* p2 = arr2;
printf("%ld\n", p2 - p1);

结果未定义。

九、总结 #

指针运算规则 #

运算 公式
p + n 地址 + n * sizeof(类型)
p - n 地址 - n * sizeof(类型)
p2 - p1 元素个数
p++, p– 移动到下一个/上一个元素

运算优先级 #

表达式 含义
*p++ 先取值,后移动
*++p 先移动,后取值
++*p 值加1
(*p)++ 先取值,值加1

应用场景 #

  • 遍历数组
  • 字符串操作
  • 内存操作
  • 数据结构实现

注意事项 #

  • 避免越界访问
  • 指针相减要求同一数组
  • 注意运算优先级
  • 检查指针有效性

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

最后更新:2026-03-26