我正在开发一个程序,我必须修改目标进程内存/读取它。
到目前为止,我使用 void* 来存储地址,如果需要更改它们,请将它们转换为 char* (一般添加偏移量或修改)
我听说过 stdint.h 中定义的该类型,但我没有看到使用它进行指针算术与 char* 转换之间的区别(至少对我来说这似乎对 C89 更友好)
所以我的问题是:我应该使用这两种方法中的哪一个来进行指针算术?在任何情况下我都应该考虑使用 uintptr_t 而不是 char* 吗?
EDIT 1
基本上我只需要知道这是否会产生
0x00F00BAA hard coded memory adress in target
process
void* x = (void*)0x00F00BAA;
char* y = (void*)0x00F00BAA;
x = (uintptr_t)x + 0x123;
y = (char*)y + 0x123;
x == y?
x == (void*)0x00F00CCD?
y == (void*)0x00F00CCD?
在评论中用户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 位偏移量存储在 64 位字的其他未使用的高位 3 位中。指针/整数转换只是复制表示形式。结果是a加1char*
指针会导致它指向下一个字节(偏移量由软件处理),但转换为uintptr_t
加 1 会导致它指向下一个word.
底线:如果需要指针算术,请使用指针算术。这就是它的用途。
(顺便说一下,gcc 有一个扩展,允许在void*
。不要在可移植代码中使用它。它还会导致一些奇怪的副作用,例如sizeof (void) == 1
.)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)