我有以下变量
uint32_t Value = 0x80
0x80表示存储器中的地址,例如
// Write 2 at address 0x80
*(uint32_t*)((uint32_t)0x80) = 2;
如何将Value转换为指针,使其指向0x80?
uint32_t *Pointer = ?? Value;
这是:
(uint32_t*)(uint32_t)Value;
返回:
warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
3条答案
按热度按时间7dl7o3gd1#
要处理整数到 * 对象 * 指针的转换,请使用可选的整数
uintptr_t
或intptr_t
类型。函数指针是另一回事。以下类型指定了一个无符号整数类型,其属性是指向
void
的任何有效指针都可以转换为该类型,然后转换回指向void
的指针,结果将与原始指针C11dr 7.20.1.4 1进行比较然后将
void *
转换为所需的类型。如果0x80不是从有效的
uint32_t *
派生的,则结果为 undefined behavior(UB)。然而,听起来OP是在一个具有内存Map数据位置的平台上。0ejtzxu12#
我来给你解释一下:给定
你想
类型
uintptr_t
,* 如果它存在 ,保证可以在任意指针类型之间转换而不会丢失信息。它不一定存在,但是在它不存在的平台上,如果没有更多的信息,你就不能安全地做你想做的事情。没有任何其他类型被官方保证具有此属性;然而,“cpp加1”是正确的,
size_t
* 通常 * 也是如此。我甚至可以说,任何平面内存架构的ABI, 不 * 使size_t
具有此属性,都是错误指定的,但它们确实存在,有时你必须使用它们。最好首先声明
Value
为指针类型:因为这样你就只需要在初始化它的时候写强制转换,而不是在使用它的时候,
你可能会在很多地方用到它。这也避免了如果
sizeof(uintptr_t) < sizeof(uint32_t)
发生的潜在问题,因为uint32_t
从不涉及地址算术;如果从0x80
到uintptr_t
的强制转换实际上截断了常量,编译器可能会抱怨,但这不应该发生在您以这种方式访问的真实的内存地址上。3htmauhk3#
好吧,比sizeof(uintptr_t)至少没有最大指针类型那么大的疯狂ABI更重要的是记住指针出处强制。
你应该能够在(void *)和uintptr_t之间进行转换,通过uintptr_t,你可以使用(void *)arg“blind cookie”来传递,例如int或unsigned int(最多做一个static_assert(sizeof(int)<= sizeof(uintptr_t),以清除设计上的疯狂破坏平台)。
但是不要通过uintptr_t * 创建 * 指针,或者以其他方式操作它:它不会有正确的出处,如果你试图解引用那个指针,像CHERRY这样的体系结构会出错并中止程序。也就是说,把它看作是 * 有效 * 指针的单行道:它可以成为一个整数类型,但它不能回到指针。
这就是为什么,如果您需要在API中使用盲cookie,您可以使用(void *)而不是最大整数类型或uintptr_t本身。这允许有效的指针,以及将不会被解引用为cookie内容的指针。