0

我正在尝试使用 void* 在内存中存储几个整数,然后检索它们,但它不断抛出“用于算术的 'void *' 类型的指针”警告。

void *a = new char[4];
memset(a, 0 , 4);


unsigned short d = 7;
memcpy(a, (void *)&d, 2);

d=8;
memcpy(a+2, (void *)&d, 2); //pointer of type ‘void *’ used in arithmetic 


/*Retrieving*/
unsigned int *data = new unsigned int();
memcpy(data, a, 2);
cout << (unsigned int)(*data);

memcpy(data, a+2, 2);  //pointer of type ‘void *’ used in arithmetic 
cout << (unsigned int)(*data);

结果符合预期,但我担心这些警告可能会在某些编译器上变成错误。还有另一种我不知道的方法吗?

我知道这在正常情况下可能是一种不好的做法,但问题陈述要求无符号整数以 2 字节数据包的形式存储和发送。如果我错了,请纠正我,但根据我的理解,使用 char* 而不是 void* 将占用 3 个字节的 3 位数字。

4

3 回答 3

3

a+2a作为指针,意味着指针被增加以允许指针类型的两个项目的空间。Vg 如果aint32 *,则a + 2表示“一个位置加上 8 个字节”。

由于void *没有类型,它只能尝试猜测您所说的 是什么意思a + 2,因为它不知道所引用类型的大小。

于 2013-10-30T01:26:52.330 回答
2

问题是编译器不知道如何处理

a+2

该指令的意思是“将指针 'a' 向前移动 2 * (sizeof-what-is-pointed-to-by-'a')”。

如果 a is void *,编译器不知道目标对象的大小(没有!),所以它给出一个错误。

你需要做:

memcpy(data, ((char *)a)+2, 2); 

这样,编译器就知道如何添加 2 - 它知道sizeof(char).

于 2013-10-30T01:31:11.083 回答
0

如果我错了,请纠正我,但根据我的理解,使用 char* 而不是 void* 将占用 3 个字节的 3 位数字。

是的,您错了,如果您将数字作为字符传输,就会出现这种情况。'char*' 只是引用 8 位值的一种方便方式 - 由于您正在接收字节对,因此您可以将目标内存视为 char 来进行简单的数学运算。但人们将“char”数组用于网络数据流是相当普遍的。

我更喜欢使用类似BYTEuint8_t明确表示“我正在使用字节”的东西,而不是 char 或其他值。

void*是一个指向未知的、更重要的是 0 大小的类型 (void) 的指针。因为大小为零,偏移数学将导致零,所以编译器告诉你它是无效的。

您的解决方案可能就像从网络接收字节到基于字节的数组一样简单。一个 int 是 32 位,4 个字节。它们不是“char”值,而是 4 字节整数的四边形。

#include <cstdint>

uint8_t buffer[4];

一旦你知道你已经填满了缓冲区,你可以简单地说

uint32_t integer = *(static_cast<uint32*>(buffer));

这是否正确取决于字节是按网络顺序还是主机顺序。我猜你可能需要:

uint32_t integer = ntohl(*(static_cast<uint32*>(buffer)));
于 2013-10-30T02:46:43.283 回答