我目前正在编写一个涉及内存地址的大量算法的内核,并且在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放在同一个地方?值得一提的是这段代码功能很好......
答案 0 :(得分:4)
您需要强制转换为指针类型才能调用memcpy
(char *
或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_t
和uintptr_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