将目标内存地址作为uint32_t传递给memcpy会发出警告

时间:2018-04-02 19:24:21

标签: c pointers memcpy

我目前正在编写一个涉及内存地址的大量算法的内核,并且在memcpy上收到以下臭名昭着的警告:

warning: passing argument 1 of 'memcpy' makes pointer from integer without a cast
   memcpy(dest, &bf, 16*sizeof(uint32_t));

抛出警告的示例是我执行以下操作时

uint32_t bf[16];

uint32_t shmem = (uint32_t)&tos_shared;
uint32_t dest = shmem - 16*sizeof(uint32_t);
memcpy(dest, &bf, 16*sizeof(uint32_t));

其中&tos_shared (0x700347a8)是堆栈内存地址的顶部。我将其转换为uint32_t (1879263144),以便我可以进行算术并得到我想要的目标地址dest (1879262952)

如何将dest转换为指针但保留目标地址,以便memcpy不会抱怨并且bf放在同一个地方?值得一提的是这段代码功能很好......

2 个答案:

答案 0 :(得分:4)

您需要强制转换为指针类型才能调用memcpychar *void *将起作用; void *在此处更为惯用。您还需要使用uintptr_t而不是uint32_t进行手动指针算法。

uint32_t bf[16];

uintptr_t shmem = (uintptr_t)&tos_shared;
uintptr_t dest = shmem - 16*sizeof(uint32_t);
memcpy((void *)dest, &bf, 16*sizeof(uint32_t));

此代码不保证可以普遍使用。但是,它是实现定义的是否可行,并且由于您正在编写内核,因此 (实现的一部分),因此您可以决定是,物理RAM的布局将始终如此这样做确实有效。

根据您的ABI,uint32_tuintptr_t可能是也可能不是相同的基本类型,但即使它们仍然使用uintptr_t,因为这更加自我记录并且将来会更容易去64位(假设你可能想要的东西)。

答案 1 :(得分:3)

使用char*&tos_shared可以获得正确的结果。您也可以使用sizeof bf来简化一下。

uint32_t bf[16];

char* shmem = (char*)&tos_shared;
void* dest = shmem - sizeof bf; // sizeof bf == sizeof(uint32_t) * 16
memcpy(dest, &bf, sizeof bf);

如果您确实需要将指针存储在整数类型中(无论如何都应该避免),正确的类型是uintptr_t