Mur*_*yev 4 c pointers char pointer-arithmetic
我正在编写一个程序,我必须修改目标进程内存/读取它.
到目前为止,我使用void*来存储地址并将其转换为char*如果我需要更改它们(添加偏移量或修改一般)
我听说过在stdint.h中定义的那个类型,但我没有看到使用它进行char*转换的指针算法的差异(这对我来说似乎更C89友好)
所以我的问题是:我应该将哪两种方法用于指针算法?在任何情况下我是否应该考虑使用uintptr_t而不是char*?
编辑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位中.指针/整数转换只是复制了表示.结果是向char*指针添加1 会导致它指向下一个字节(在软件中处理偏移量),但转换为uintptr_t1并添加1将导致它指向下一个字.
底线:如果需要指针算法,请使用指针算法.这就是它的用途.
(顺便说一句,gcc有一个允许指针算术的扩展void*.不要在便携式代码中使用它.它也会引起一些奇怪的副作用,比如sizeof (void) == 1.)