Kos*_*Kos 77 c c++ pointers casting
普通的民间传说说:
类型系统存在是有原因的.整数和指针是不同的类型,它们之间的转换在大多数情况下是一种弊端,可能表示设计错误,应该避免.
即使执行了这样的强制转换,也不应该对整数和指针的大小做出任何假设(强制void*转换int是使代码在x64上失败的最简单方法),而不是int应该使用intptr_t或uintptr_t来自stdint.h.
知道什么时候执行这样的演员表真的有用吗?
(注意:可移植性价格的代码稍微短一点并不算"实际上有用".)
我知道一个案例:
更多的东西?
Pla*_*aHH 38
当它们以某种方式需要成为hashsum的一部分时,我有时会将指针转换为整数.我还将它们转换为整数,以便在某些实现中对它们进行一些操作,在这些实现中保证指针总是剩下一个或两个备用位,在那里我可以在左/右指针中编码AVL或RB树信息而不是额外的会员.但这完全是具体的实现,我建议永远不要将其视为任何一种常见的解决方案.我还听说有时可以用这样的东西实现危险指针.
在某些情况下,我需要每个对象的唯一ID,我将其作为请求ID传递给服务器.根据我需要保存一些内存的上下文,这是值得的,我使用我的对象的地址作为这样的id,并且通常必须将它转换为整数.
当使用嵌入式系统(例如在佳能相机中,请参阅chdk)时,通常会有神奇的瑕疵,因此(void*)0xFFBC5235在那里经常会发现一个或类似的
编辑:
只是偶然发现(在我的脑海里),pthread_self()它返回一个pthread_t,它通常是无符号整数的typedef.在内部,虽然它是一个指向某个线程结构的指针,表示有问题的线程.通常它可能在别处用于不透明的句柄.
Fle*_*exo 15
在检查一般类型的对齐时,它可能很有用,这样就可以通过断言捕获未对齐的内存而不仅仅是SIGBUS/SIGSEGV.
例如:
#include <xmmintrin.h>
#include <assert.h>
#include <stdint.h>
int main() {
void *ptr = malloc(sizeof(__m128));
assert(!((intptr_t)ptr) % __alignof__(__m128));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
(在实际代码中我不会赌博malloc,但它说明了这一点)
一个例子是在Windows中,例如SendMessage()和PostMessage()函数.它们采用HWnd(窗口的句柄),消息(整数类型)和消息的两个参数,a WPARAM和a LPARAM.两种参数类型都是完整的,但有时您必须传递指针,具体取决于您发送的消息.然后你将必须指向一个LPARAM或WPARAM.
我通常会像瘟疫一样避免它.如果需要存储指针,请使用指针类型(如果可能).
在我看来,最有用的案例是实际上有可能使程序更高效的程序:许多标准和公共库接口只接受一个void *参数,它们将传递回某种类型的回调函数.假设您的回调不需要任何大量数据,只需要一个整数参数.
如果回调将在函数返回之前发生,您可以简单地传递本地(自动)int变量的地址,一切都很好.但对于这种情况pthread_create,最好的现实示例是,"回调"并行运行,并且您无法保证在pthread_create返回之前它能够通过指针读取参数.在这种情况下,您有3个选项:
malloc一个单一int的新线程读取free它.int和同步对象(例如信号量或屏障)的调用者本地结构,并在调用后让调用者等待它pthread_create.int为void *并按值传递它.选项3比任何其他选项都更有效,两者都涉及额外的同步步骤(对于选项1,同步在malloc/中free,并且几乎肯定会涉及一些成本,因为分配和释放线程不相同) .
在嵌入式系统中访问内存映射硬件设备非常常见,其中寄存器位于存储器映射中的固定地址.我经常在C与C++中对硬件进行不同的建模(使用C++可以利用类和模板),但一般的想法可以用于两者.
一个简单的例子:假设你有一个硬件定时器外设,它有2个32位寄存器:
一个自由运行的"滴答计数"寄存器,以固定速率递减(例如每微秒)
一个控制寄存器,它允许你启动定时器,停止定时器,当我们将计数减少到零时启用定时器中断等.
(注意,实时定时器外设通常要复杂得多).
这些寄存器中的每一个都是32位值,定时器外设的"基地址"是0xFFFF.0000.您可以按如下方式对硬件进行建模:
// Treat these HW regs as volatile
typedef uint32_t volatile hw_reg;
// C friendly, hence the typedef
typedef struct
{
hw_reg TimerCount;
hw_reg TimerControl;
} TIMER;
// Cast the integer 0xFFFF0000 as being the base address of a timer peripheral.
#define Timer1 ((TIMER *)0xFFFF0000)
// Read the current timer tick value.
// e.g. read the 32-bit value @ 0xFFFF.0000
uint32_t CurrentTicks = Timer1->TimerCount;
// Stop / reset the timer.
// e.g. write the value 0 to the 32-bit location @ 0xFFFF.0004
Timer1->TimerControl = 0;
Run Code Online (Sandbox Code Playgroud)
这种方法有100种变体,其优缺点可以永远讨论,但这里的重点仅仅是说明将整数转换为指针的常见用法.请注意,此代码不可移植,与特定设备绑定,假设内存区域不受限制等.