用非零值初始化void指针的正确(或最安全)方法
correct (or safest )way of initializing void pointer with non-zero value?
以下作品:
void* p = reinterpret_cast<void*>(0x1000);
但看起来"不正确/不安全",例如0x1000是int
,甚至不是uintptr_t
,我可以解决这个问题,但有更好/更安全的铸造方法吗?
0x1000是
int
,甚至不是uintptr_t
,我可以解决这个问题,但有更好/更安全的方法来铸造吗
0x1000
是int
,在reinterpret_cast<void*>(0x1000)
中,编译器发出一个符号扩展指令(此处符号为0)或一个带有立即数操作数的普通寄存器加载指令,以使值与void*
一样宽。
由于许多原因,编译器不可能知道0x1000
是否代表有效地址,因此它必须遵守并假设它是有效地址。
用reinterpret_cast
将表示地址的整数转换为指针是目前的做法。
您可以使用reinterpret_cast
从整数创建指针。
然而,不指向现有对象的指针(或数组中最后一个元素后1的指针,该对象被视为虚数组中唯一的元素,或为空指针)具有无效指针值。取消引用是UB,其他具有无效指针值的操作是特定于实现的,因此您需要确保编译器允许使用这些指针执行操作。
void* p = reinterpret_cast<void*>(0x1000); // invalid pointer,
// operations on it are implementation defined
§6.7.2化合物类型[基本化合物]
[…]指针类型的每个值都是以下值之一:
3.1——指向对象或函数的指针(据说指针指向对象或功能),或
3.2——指针经过对象的末尾(8.5.6),或
3.3——该类型或的空指针值(7.11)
3.4——指针值无效
§8.5.1.10重新解释cast[expr.relinterpret.cast]
- 指针可以显式转换为任何足以容纳它的整数类型。映射函数由实现定义。[…]
- 积分类型或枚举类型的值可以显式转换为指针。转换为整数的指针足够的大小(如果实现中存在任何此类大小)并返回相同的指针类型将具有其原始值;之间的映射指针和整数以其他方式由实现定义
允许从整数转换为指针,但如果结果指针值没有指向现有对象(或经过对象的对象),则结果指针的值无效。
现在关于如何处理无效指针:
§6.6.4存储持续时间[basic.stc]
- […]未定义通过无效指针值的指示和将无效指针值传递给释放函数行为任何其他对无效指针值的使用都具有实现定义的行为35
35)有些实现可能会定义复制无效指针值导致系统生成的运行时故障。
这篇文章被大量编辑,因为它在第一次迭代中是错误的。热烈感谢社区对我的纠正和挑战。
tl;医生:你可能就是不应该这么做
以下。。。看起来"不正确/不安全"。。。有更好/更安全的铸造方法吗?
正如另一个答案所指出的;不正确的";达到实现定义行为的程度。此外,你在使用一个神奇的数字。
但问题不在于选角,我相信。我真的有点怀疑你是否需要初始化一个带有文字地址的void*
变量。为什么?
-
如果该地址有某种类型的值,那么不要使用
void *
,而是使用类型指针。即使您以后想将指针传递给memset()
或memcpy()
,甚至是一些使用void *
的回调函数,也要延迟类型擦除。 -
你从哪里得到那个号码的?你肯定知道幻数是坏的,对吧?好吧,至少使用之类的东西
constexpr const uintptr_t sound_card_memory_mapped_buffer_address { 0x1000 };
这解决了您的一个问题(而不是
uintptr_t
),而且读起来也更清楚,即使您使用void *
:void* p = reinterpret_cast<void*>(sound_card_memory_mapped_buffer_address);
-
p
是一个糟糕的变量名称选择。根据用途将其重命名。 -
您真的需要初始化
p
吗?:-
如果你现在不使用它,为什么还要初始化它?尽量不要声明它,直到它即将被使用(如果有的话)。
-
如果你打算使用它,为什么还要申报呢?尝试:
do_something_with(sound_card_memory_mapped_buffer_address);
并且看不到CCD_ 21。
-
很明显,我要问的问题比答案多,因为你只给我们提供了一句话。
- 将传入的网络"char*"数据转换为"uint8_t"并返回的安全方法是什么?
- 在 c++ 中从执行的 shell 命令获取返回状态的安全方法是什么?
- 在C++线程内实现多个计时器的最安全方法
- 最有效的安全方法将 std::map<int, std::shared_ptr> 转换为 std::<Base>map<int, std::shared_ptr<D
- 重新分配指针阵列的一部分的安全方法
- 将整数添加到数组值而无需调用它的最安全方法
- 使用括号运算符实现矩阵类的安全方法
- 将空隙动态铸造到类型的安全方法?
- C/通过套接字发送time_t的最安全方法
- 交换两个类实例的最安全方法
- 将uint16_t投射到wchar_t的安全方法
- 从字符串中读取溢出双倍作为'inf'的安全方法
- 期货是检查单个线程完成情况的安全方法吗
- 在C++中动态分配向量的安全方法是什么
- 在C++类中构建互斥保护的线程安全方法
- C++和跳出动态生成代码的安全方法
- 这是实现错误处理的安全方法吗
- 将长整数转换为字符数组的最安全方法是什么
- 缓存 PID 到端口映射窗口的安全方法
- 将无符号长整整除以无符号长整型的最安全方法