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

为何指针算术运算结果错误?4096字节偏移计算异常

指针偏移计算错误的原因分析

我尝试每次将指针向前移动4096字节,编写的代码如下:

#include <stdint.h>
#include <stdio.h>
void calculate(void* a)
{
    uintptr_t stride = 4096; 
    uint64_t *buff = (uint64_t*)a;
    for (uintptr_t offset = 0; offset < 20000; offset += stride)
    {
        fprintf(stdout, "%s: stride = 0x%x offset = 0x%x buff = %p offset+buff = %p\n", __func__, stride, offset, buff, offset+buff);
    }
}

int main(void)
{
    void* address = 0x7f5b588d1000;

    calculate(address);

    return 0;
}

但运行后输出结果为:

calculate: stride = 0x1000 offset = 0x0 buff = 0x7f5b588d1000 offset+buff = 0x7f5b588d1000
calculate: stride = 0x1000 offset = 0x1000 buff = 0x7f5b588d1000 offset+buff = 0x7f5b588d9000

可以看到计算结果显示:

0x7f5b588d1000 + 0x1000 = 0x7f5b588d9000

而预期结果应为0x7f5b588d2000,请问该计算错误的原因是什么?


错误原因

问题核心是C语言指针算术的自动缩放特性:

  • 你将void*类型的输入指针强制转换为uint64_t*类型,而指针的偏移运算会根据其指向的类型大小自动调整偏移量。
  • uint64_t占8字节,所以当你执行offset + buff时,编译器会把offset的值当成「uint64_t元素的个数」,而非字节数。
  • 你的stride是4096(即0x1000),实际计算为:0x7f5b588d1000 + 0x1000 * 8 = 0x7f5b588d1000 + 0x8000 = 0x7f5b588d9000,这就是输出结果的由来。

修复方案

有两种直接的修复方式:

  1. 使用char*类型进行字节级偏移(char的大小是1字节,偏移不会被缩放):
#include <stdint.h>
#include <stdio.h>
void calculate(void* a)
{
    uintptr_t stride = 4096; 
    char* buff = (char*)a; // 转为char*,确保按字节偏移
    for (uintptr_t offset = 0; offset < 20000; offset += stride)
    {
        fprintf(stdout, "%s: stride = 0x%x offset = 0x%x buff = %p offset+buff = %p\n", __func__, stride, offset, buff, buff + offset);
    }
}

int main(void)
{
    void* address = 0x7f5b588d1000;
    calculate(address);
    return 0;
}
  1. 若必须使用uint64_t*,则将字节步长转换为元素个数:
#include <stdint.h>
#include <stdio.h>
void calculate(void* a)
{
    uintptr_t byte_stride = 4096; 
    uint64_t *buff = (uint64_t*)a;
    uintptr_t elem_stride = byte_stride / sizeof(uint64_t); // 计算每个步长对应的元素个数
    for (uintptr_t offset = 0; offset < 20000 / sizeof(uint64_t); offset += elem_stride)
    {
        // 输出时转换回字节数显示
        fprintf(stdout, "%s: stride = 0x%x offset = 0x%x buff = %p offset+buff = %p\n", 
                __func__, (unsigned int)byte_stride, 
                (unsigned int)(offset * sizeof(uint64_t)), 
                buff, buff + offset);
    }
}

int main(void)
{
    void* address = 0x7f5b588d1000;
    calculate(address);
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 09:19:59