基本上我想将指针的地址存储在缓冲区中。不要问我为什么
char * buff = "myBuff";
char * myData = (char*)malloc(sizeof(char*));
int addressOfArgTwo = (unsigned int)buff;
memcpy(myData, &addressOfArgTwo, sizeof(char*));
cout << "Int Val: " << addressOfArgTwo << endl;
cout << "Address in buffer:" << (unsigned int)*myData << endl;
我看不出为什么上面的代码不起作用。它输出:
Int Val: 4472832
Address in buffer:0
当Int Val&amp;缓冲区中的地址应该相同。感谢
答案 0 :(得分:8)
取消引用char *,产生一个char,然后将该1字节字符转换为int,而不是整个4字节的地址(如果这是32位机器,则在64位上为8字节) 。 4472832是十六进制的444000。在小端机器上,你抓住最后一个00。
*((unsigned int*)myData)
应该会显示正确的数字。
答案 1 :(得分:1)
Instead of (int)*myData, it should be *((int*)myData)
答案 2 :(得分:1)
cout << "Address in buffer:" << *((unsigned int*)myData) << endl
答案 3 :(得分:1)
这通常是危险的:
*((unsigned int*)myData)
Intel IA-32(每个人都习惯)支持未对齐访问,但其他一些架构则不支持。它们需要对齐变量(1字节边界上的8位数据,2字节边界上的16位数据和4字节边界上的32位数据)。在需要对齐的体系结构上,未对齐的访问将返回损坏的数据或抛出CPU异常。我已经看到它在过去的工作中导致现实生活中的错误,这是一个微妙的错误导致文件系统损坏,因为我们使用的软件包附带的磁盘驱动程序(在嵌入式平台上)。
在这个孤立的情况下,你可以看到myData的地址来自malloc(),这应该意味着它适合所有类型的指针对齐,但是如果你不喜欢将一个较小的指针指向一个较大的指针通常是一个危险的做法不知道指针来自哪里。
从任意内存位置提取32位整数的安全方法是声明一个临时的32位整数并对其执行复制,将源内存视为原始字符数组:
unsigned int GetUnalignedLittleEndianUInt32(void *address)
{
unsigned char *uc_address = (unsigned char *)address;
return (
(uc_address[3] << 24) |
(uc_address[2] << 16) |
(uc_address[1] << 8) |
uc_address[0]
);
}
或更一般地(带有一些函数调用开销):
unsigned int GetUnalignedUInt32(void *address)
{
unsigned int value;
memcpy(&value, address, sizeof(value));
return value;
}
实际上就是你在第一时间将指针放在那里的memcpy()的反面。
虽然,将指针视为int:
int addressOfArgTwo = (unsigned int)buff;
如果你在32位和64位架构之间移动,那么也很危险,正如迈克尔指出的那样。指针并不总是32位整数。考虑使用以后可以更改的typedef。 Linux上的约定是指针与long的大小相同。在Windows上,有typedef INT_PTR,UINT_PTR,LONG_PTR和ULONG_PTR。
所以,我最后会建议(无论如何在Windows上):
ULONG_PTR GetAddressAtAddress(void *address)
{
ULONG_PTR value;
memcpy(&value, address, sizeof(value));
return value;
}