You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

指针递减赋值后读取值异常的原因及解决办法

问题

尝试在递减指针的同时,为指针指向的地址赋值。赋值时显示值已正确设置,但再次读取时却无法得到正确的值。请问这是什么原因,该如何解决?

以下是尝试的代码:

int a = 0;
int* sp = &a;
int* start_sp = &a;

for (int i = 0; i <= n; i++) {
    *sp = i;
    printf("%d, %d\n", *sp, sp);
    sp--;
}

sp = start_sp;
printf("\n");
    
for (int i = 0; i <= n; i++) {
    printf("%d, %d\n", *sp, sp);
    sp--;
}

得到的输出是:

0, 6291028
1, 6291024
2, 6291020
3, 6291016
4, 6291012

0, 6291028
1, 6291024
0, 6291020
6283584, 6291016
0, 6291012
原因与解决方法

核心原因

  • 非法访问未分配内存:你仅声明了单个int变量a,它只占用一块int大小的内存(示例中的6291028)。第一次循环中sp--后,指针指向的是a内存地址之前的区域——这些内存不属于你的程序,要么是未分配的空闲内存,要么被系统/其他程序占用。
  • 未定义行为的假象:第一次循环中给非法地址赋值后立刻读取能显示“正确值”,只是因为此时该内存区域还没被其他操作覆盖,但这属于C语言中的未定义行为——标准不保证对非法内存的读写结果,任何后续操作都可能篡改这些数据。
  • 内存被后续操作篡改:当程序完成第一个循环、执行重置指针等操作时,系统或程序的其他部分可能已经修改了这些非法内存区域的数据,导致第二次读取时得到错误或随机值。

解决办法

要实现连续的指针读写,必须先分配属于程序的合法内存,有两种常用方式:

1. 使用固定大小数组

如果n是编译时已知的常量,直接声明对应大小的数组:

// 假设n为4,可根据实际需求调整
int n = 4;
int arr[n + 1]; // 分配n+1个int的连续内存
int* sp = &arr[n]; // 指向数组末尾,递减时依次填充前面的元素
int* start_sp = sp;

for (int i = 0; i <= n; i++) {
    *sp = i;
    printf("%d, %p\n", *sp, (void*)sp); // 用%p打印指针是标准做法
    sp--;
}

sp = start_sp;
printf("\n");
    
for (int i = 0; i <= n; i++) {
    printf("%d, %p\n", *sp, (void*)sp);
    sp--;
}

2. 动态分配内存

如果n是运行时才确定的值,用malloc动态分配内存,记得用完后释放:

int n = 4;
// 分配n+1个int的内存,检查分配是否成功
int* arr = (int*)malloc((n + 1) * sizeof(int));
if (arr == NULL) {
    printf("内存分配失败\n");
    return 1;
}

int* sp = &arr[n];
int* start_sp = sp;

// 读写逻辑和数组版本一致
for (int i = 0; i <= n; i++) {
    *sp = i;
    printf("%d, %p\n", *sp, (void*)sp);
    sp--;
}

sp = start_sp;
printf("\n");
    
for (int i = 0; i <= n; i++) {
    printf("%d, %p\n", *sp, (void*)sp);
    sp--;
}

free(arr); // 释放动态分配的内存,避免内存泄漏

注意:打印指针时必须使用%p格式符,并将指针强制转换为void*,这是C语言标准规定的正确方式,用%d打印指针属于非标准行为,可能导致输出错误。

内容的提问来源于stack exchange,提问作者DaBoat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 06:32:50