是否存在将长整型转换为指针有效的情况
Are there cases where casting a long to pointer is valid
在我的C++学习过程中,我在x86中遇到了这样的代码,我不明白:
unsigned long value = 50;
unsigned char* result = (unsigned char*)value;
检查指针会给出内存访问错误(即我无法写入std::cout << *result;
(。如果有的话,铸造线应该是这样的:
unsigned char* result = (unsigned char*)&value;
但事实并非如此。所以我的问题是,在什么情况下(如果有的话(第一个铸件可用?或者换句话说,是否可以从指针中获取数据?
我目前正在研究一些数字信号处理,其中包括对ADI公司的DSP进行编程。以下是他们随开发板附带的一个.h文件中的一个小片段:
#define pUART0THR ((volatile unsigned int *)0x3c00) /* Transmit Holding Register */
#define pUART0RBR ((volatile unsigned int *)0x3c00) /* Receive Buffer Register */
#define pUART0DLL ((volatile unsigned int *)0x3c00) /* Divisor Latch Low Byte */
#define pUART0IER ((volatile unsigned int *)0x3c01) /* Interrupt Enable Register */
我敢打赌,如果您深入研究几乎任何其他嵌入式系统的标题,您将能够找到类似的东西。
在这种情况下,0x3c00
是一个内存地址,您可以将字节写入其中,并让硬件UART模块读取它并通过串行端口传输它。0x3c01
是寄存器的地址,如果您设置第二位(位 1(,那么当 UART 发送缓冲区(地址0x3c00
处(为空时,您将获得硬件中断 = 您放置在那里的字节已被发送。
但是,为了让您不必记住所有这些地址,并获得一些漂亮的(或至少更令人难忘的(名称来称呼它们,它们有一堆定义,如上面。
将整数强制转换为指针的一个潜在原因是通过接受指针的 API 传输该整数值。
例如,许多与回调相关的 API 接受将void *user_data
参数作为参数传递给回调函数。请考虑以下函数:
void do_async_thing(args..., void (* callback) (int result, void *user_data), void *user_data);
如果你只需要传递给回调一个整数,
那么你可以写:do_async_thing(
args...,
[](int result, void *request_idx) {
std::cout << "request " << reinterpret_cast<std::uintptr_t>(request_idx) << " returned " << result;
},
reinterpret_cast<void *>(std::uintptr_t{request_idx})
);
当然你应该使用std::uintptr_t
,而不是unsigned long
(例如,在 Windows 上unsigned long
是 32 位(。
另一个原因是,在您的特定平台上,您碰巧知道该地址(例如,在某些嵌入式设备上(存在有效对象。
归根结底,这都是实现定义的。std::uintptr_t
甚至可能不存在于特定平台上。
在某些情况下,但通常不合适。
只有在以下情况下,转换才有效:
long
是足够大的类型,可以表示所有地址。这不能保证。事实上,long
在 64 位 Windows 系统上不够大。有一个整数类型可以保证为此目的正确调整大小:std::uintptr_t
。
当然,除非您打算使用指针执行某些操作,否则此转换完全没有意义。这些东西是否有效取决于更多的要求。
- 如果转换后的指针值无效,即不引用分配的存储区域,则通过指针进行间接具有未定义的行为。任何其他用途(例如将值与另一个指针进行比较(都具有实现定义的行为。
- 如果指针指向的对象在其生存期之外,但具有分配的存储空间,则只能以有限的方式使用该指针。通过指针访问内存仍然是典型的(例外情况适用(未定义的行为,但例如,您可以将值相等与另一个有效指针进行比较。请参阅标准部分 [basic.life]、[class.base.init] 和 [class.cdtor] 了解有关允许的内容的详细信息。
- 如果指针指向其生存期内的对象,并且指针属于相同类型(或兼容类型(,则可以间接通过指针访问指向的对象。
请注意,从整数到指针的转换映射是实现定义的。几乎唯一可以保证的是,转换为足够大小的整数的指针可以转换回相同的值。
以上仅描述转换后的指针的转换和使用有效的情况。另一个问题是这样做是否有任何意义。这些用例在桌面/服务器系统上很少见(参见 andrey 的答案示例(,但在嵌入式系统上,有时会有硬编码地址用于与硬件通信(参见 Frodyne 的答案以获取示例(。
unsigned long value = 50;
unsigned char* result = (unsigned char*)value;
现在指针result
包含数字50
,换句话说,它指向地址50
。但是在现代平台上,您不能简单地寻址任何内存地址。
因此,此代码将导致未定义的行为(通常是崩溃(。
std::cout << *result;
- 调整大小后指向元素值的指针unordered_map有效?
- 如何在工厂方法中返回指向基于基础操作系统的派生类的有效指针
- 为什么在引用指针时将 const 放在 & 符号的左侧有效,而在右侧则无效?
- C++ 返回指向函数内定义的静态数组的指针是否有效?
- 通过指针调用模板类成员函数 [为什么这是有效的 c++]?
- free():在有效指针异常中-使用流读取巨大文件时
- 释放 std::vector 中指针内存的最有效方法是什么?
- C++ 常量指向文字的指针有效吗?
- 是否存在将长整型转换为指针有效的情况
- 将指针传递给函数在简单的情况下有效,但在"class" -izing 之后不起作用
- 在映射中插入更多元素后,指向 QMap 中元素的指针是否仍然有效?
- 指向派生类的指针中的"static_cast<Base*>(static_cast<void*>(派生))"何时有效?
- 如何有效地使用 std::async 对指针数组执行操作
- 当程序从该函数调谐器时,指向在函数中声明和定义的某些 C 字符串的指针不再有效.为什么?
- EIGEN地图类:将C阵列映射到VectorXD指针以有效的方式
- 如何检查指针后面的对象是否有效或已删除?
- C++数组超出范围访问以计算指针有效?
- 提升::进程间managed_shared_memory指针有效作用域
- 为什么const_cast away volatile只对指针有效?
- 为什么将const类型的智能指针强制转换为类型的智能指针有效?