C - 为什么在进行指针运算时转换为uintptr_t vs char *

时间:2017-04-14 20:15:09

标签: c pointers char pointer-arithmetic

我正在开发一个程序,我必须修改目标进程内存/读取它。

到目前为止,我使用void *来存储地址并将其转换为char *,如果我需要更改它们(添加偏移或修改一般)

我听说过在stdint.h中定义的那种类型,但是我没有看到使用它进行char *转换的指针算术的差异(这对我来说似乎更加C89友好)

所以我的问题:我应该将哪两种方法用于指针算法?我是否应该考虑在任何情况下使用uintptr_t而不是char *?

编辑1

基本上我只需要知道这是否会产生

while (( $# )); do
    case "$1" in
    --old-value) old+=("$2") ;;
    --new-value) new+=("$2") ;;
    --exclude) shift; exc=("$@") ; break ;;
    --*) echo "bad arg" ; exit 1 ;;
    esac
    shift;shift
done
printf "old: %s\n" "${old[@]}"
printf "new: %s\n" "${new[@]}"
printf "exc: %s\n" "${exc[@]}"

1 个答案:

答案 0 :(得分:6)

在评论中,用户 R .. 指出,如果代码处理的地址在当前进程中无效,则以下内容可能不正确。我已经要求OP澄清了。

如果您关心代码的可移植性,请不要将uintptr_t用于指针运算。 uintptr_t是整数类型。对它的任何算术运算都是整数运算,而不是指针运算。

如果您有一个void*值并且想要为其添加字节偏移量,那么转换为char*是正确的方法。

uintptr_t值的算术可能与char*算术的算法相同,但绝对不能保证。 C标准提供的唯一保证是您可以将void*值转换为uintptr_t并再次返回,结果将与原始指针值进行比较。

标准并不保证uintptr_t存在。如果没有足够宽的整数类型来保存转换后的指针值而不丢失信息,那么实现就不会定义uintptr_t

我实际上在系统(Cray矢量机器)上工作,uintptr_t上的算术不一定有效。硬件具有64位字,机器地址包含字的地址。类Unix操作系统需要支持8位字节,因此字节指针(void*char*)包含一个字地址,其中3位偏移存储在其他未使用的高位3位中。 64位字。指针/整数转换只是复制了表示。结果是向char*指针添加1将导致它指向下一个字节(在软件中处理偏移量),但转换为uintptr_t并添加1会导致它指向下一个

底线:如果需要指针算法,请使用指针算法。这就是它的用途。

(顺便说一句,gcc有一个允许在void*上进行指针运算的扩展。不要在便携式代码中使用它。它还会导致一些奇怪的副作用,比如sizeof (void) == 1。)