解决 cast from pointer to integer of different size

保留现场

void* foo(void *dst, ...) {
    // some code
    unsigned int offset = (unsigned int) dst % 8; // warning here!
    // some code continue...
}

写驱动程序时经常会直接对地址进行修改,配置寄存器的值,也会将地址的值作为数据进行传递,这就会遇到一个问题,指针强转成整型,类型不匹配数据丢失的问题。

探究原因

出现这个警告的原因是,将void*类型强转成unsigned int是不可移植的。什么叫不可移植呢?

我们知道指针类型,在 32 位系统下是 4 字节,在 64 位系统下是 8 字节,而unsigned int不管在什么系统下都是是 4 字节,所以,如果将void*类型强转成unsigned int,在 64 位系统下就没有足够的空间保存真正的数据。

解决方法

粗暴地用double来接收

先接收,再截断:

void* foo(void *dst, ...) {
    // some code
    unsigned int offset = (unsigned int)(unsigned double) dst % 8; // warning here!
    // some code continue...
}

uintptr_t

uintptr_t 保证足够宽,以便将 void* 转换为 uintptr_t 并再次返回将产生原始指针值。还有一个类型 intptr_t,它是有符号的;

#include <stdint.h>
// 或者 <inttypes.h>
void* foo(void *dst, ...) {
    // some code
    unsigned int offset = (uintptr_t) dst % 8; // warning here!
    // some code continue...
}