在C语言中使用指针变量保存的地址进行模运算

3
作为课程的一部分,我需要以特定方式打印输出,将其分成每个块16字节。我已经搜索了相当长时间,以找到将指针强制转换为int或其他执行模数或除数余数操作的方法,以存储在变量中的指针地址。我遇到了障碍,这里是否有人知道我如何执行这个看似简单的操作?以下是该函数的基本形式:
void printAddress(char *loc, char *minLoc, char *maxLoc) {
    minLoc = (loc - (loc % 16));
    maxLoc = minLoc + 16;
    printf("%p - %p - %p", minLoc, loc, maxLoc);
}

我删除了所有尝试转换的代码,以便更清楚地说明我的意图。

是的,非常抱歉!到目前为止,我只完成了查找块的开头和结尾的部分。我已经将文本文件的内容存储在内存中,并正在搜索由字符给出的ASCII值。当我找到它时,我会打印字符的地址以及从地址开始的周围数据,该地址是16的倍数。因此,如果它位于低地址处,loc可能指向26的地址,这种情况下,我需要打印从16到31的地址块。 - ZapTap
1
你的一个问题是尝试打印指针的整数表示。用于指针的正确格式说明符是 %p - ciphermagi
@ciphermagi 我已经在问题中修复了这个问题 - 不过我仍然需要找到块的边界。 - ZapTap
创建一个新指针并向内存后退。但是,如果您试图执行所描述的操作,则这是非常糟糕的事情,因为您很容易超出边界。我想知道您是否意味着它应该打印从index%16到index%31而不是address - ciphermagi
我想要表达的是,在内存中移动是非常危险的,因为你很容易访问到数组外部的边界。但是,如果你知道你的数组从哪里开始和结束,那么你可以简单地从索引打印,解决方案就是跟踪你当前所在的索引,然后将你的索引而不是地址减少到最接近16的倍数。减少地址并不会检查你是否仍然在数组中。 - ciphermagi
显示剩余4条评论
2个回答

6
您要查找的类型是uintptr_t,定义在<stdint.h>中。它是一个无符号整数类型,足够大以容纳任何指向数据的指针。格式在<inttypes.h>中。它们允许您正确地格式化代码。当您包含<inttypes.h>时,不必再包含<stdint.h>。如果您使用64位处理器,则可以选择16;如果您使用32位处理器,则可以选择8。
void printAddress(char *loc)
{
    uintptr_t absLoc = (uintptr_t)loc;
    uintptr_t minLoc = absLoc - (absLoc % 16);
    uintptr_t maxLoc = minLoc + 16;
    printf("0x%16" PRIXPTR " - 0x%16" PRIXPTR " - 0x%16" PRIXPTR "\n",
           minLoc, absLoc, maxLoc);
}

您也可以写成:

    uintptr_t minLoc = absLoc & ~(uintptr_t)0x0F;

参见解决让我困惑的C面试题中的内存对齐问题

请注意,理论上可能存在一个未定义uintptr_t的系统;我不知道所有系统,但我知道没有一个实际不支持它。


现在,使用此方法是否存在任何缺点?还是说从所有实际目的来看,它只会被视为任何其他整数类型? - ZapTap
2
uintptr_t 的目的是将指针视为普通的无符号整数类型。 - Pod
1
实际上,进一步研究后,我认为将任何突变转换为uintptr_t,然后再将其强制转换回指针,当该指针被取消引用时,“未定义行为”,因为您可能会使编译器在背后执行的所有内部对齐操作无效。虽然在99.99%的情况下不会出现这种情况;) - Pod
uintptr_t是一个普通的无符号整数类型;它是由系统特别指定的一种类型,不一定是标准类型,足够大以容纳数据指针。如果系统使用96位数据指针并支持128位无符号整数类型,则uintptr_t可能是该128位无符号类型的别名。 - Jonathan Leffler
1
@Pod:如果您修改值,使其超出指针最初指向的任何数组(或值)的范围,那么您正在走薄冰。 如果您的修改将修改后的值保持在数组边界内,并具有适当对齐的值,则非常不可能遇到问题。 但从理论上讲,这是一种可移植性风险,因此当您迁移代码时,应该仔细隔离系统中需要考虑可移植性假设的部分。 - Jonathan Leffler

0

我可能没有完全理解问题,但对我来说,看起来你是在尝试做一个老式的十六进制转储?

void hexdump(char *buf, int size)
{
    int i;

    for (i = 0; i < size; i++)
    {
        if (i % 16 == 0)
        {
            puts("");
            printf("%p", &buf[i]);
        }

        printf("%02x ", buff[i]);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接