0

I'm trying to store a couple of ints in memory using void* & then retrieve them but it keeps throwing "pointer of type ‘void *’ used in arithmetic" warning.

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);

The results are as per expectation but I fear that these warnings might turn into errors on some compiler. Is there another way to do this that I'm not aware of?

I know this is perhaps a bad practice in normal scenario but the problem statement requires that unsigned integers be stored and sent in 2 byte packets. Please correct me if I'm wrong but as per my understanding, using a char* instead of a void* would have taken up 3 bytes for 3-digit numbers.

mindreader
  • 1,763
  • 1
  • 20
  • 35
  • 2
    why you want `void *`? you can use `char *` – Bryan Chen Oct 30 '13 at 01:25
  • new operator dynamically allocate memory so there is no need for memset. and for generic datatype, C++ have templetes. – Rahul Oct 30 '13 at 01:26
  • I need data in binary, so that the unsigned ints are stored in 2 bytes. I suppose char* would take 3 bytes for 3 digit numbers? – mindreader Oct 30 '13 at 01:26
  • I know that upvoting isn't appropriate as a repair, but neither is downvoting simply stoopit questions ... – πάντα ῥεῖ Oct 30 '13 at 01:30
  • 1
    This is just wrong on so many levels. What happens when you take your code to an older 32 bit machine? Why didn't you use an `int` array, or a data structure that contains two `int` data members? – David Hammen Oct 30 '13 at 01:34
  • @mindReader _'and sent in 2 byte packets'_ then you might need to consider correct conversion from/to host/network byte order as well! – πάντα ῥεῖ Oct 30 '13 at 01:41
  • @g-makulik: yes, I'm doing that. This was just a part of code that I posted. Apologies if the question was vague. – mindreader Oct 30 '13 at 01:46
  • @mindReader Aha. I was just wondering, because I couldn't spot any use of `htons()`/`ntohs()` functions, or some similar mechanism to get the low-/high-bytes in the right order. – πάντα ῥεῖ Oct 30 '13 at 01:50
  • @g-makulik : okay. haven't tested the whole code yet. So, can't say if that's working. I'm a newbie in c++ & learning as I'm doing. – mindreader Oct 30 '13 at 02:04
  • @mindReader So did you really meant _'sent'_ by means to send over network sockets and different host machines? Then you definitely need to consider [network/host](http://www.gnu.org/software/libc/manual/html_node/Byte-Order.html) byte orders – πάντα ῥεῖ Oct 30 '13 at 02:10

3 Answers3

3

a+2, with a being a pointer, means that the pointer is increased to allow space for two items of the pointer type. V.g., if a was int32 *, a + 2 would mean "a position plus 8 bytes".

Since void * has no type, it can only try to guess what do you mean by a + 2, since it does not know the size of the type being referred.

SJuan76
  • 24,532
  • 6
  • 47
  • 87
  • Thanks for your reply. I am indeed interested in a+2 memory location. How can that be accessed? – mindreader Oct 30 '13 at 01:30
  • 1
    cast `a` to a byte sized pointer (or a double byte sized pointer, but then add only `1`). The obvious choice would be `char` but its actual size depends of the platform, so check it. – SJuan76 Oct 30 '13 at 01:34
  • 2
    @mindReader `a+2(what???)` 2 bytes? You'll need to be explicit, `char` and `int` types occupy different memory space, thus it's reflected by pointer arithmetic! – πάντα ῥεῖ Oct 30 '13 at 01:35
  • ah ok! I'm sorry I didn't realize. I meant 2 bytes. – mindreader Oct 30 '13 at 01:41
  • More info: http://stackoverflow.com/questions/3523145/pointer-arithmetic-for-void-pointer-in-c – SJuan76 Oct 30 '13 at 02:09
2

The problem is that the compiler doesn't know what to do with

a+2

This instruction means "Move pointer 'a' forward by 2 * (sizeof-what-is-pointed-to-by-'a')".

If a is void *, the compiler doesn't know the size of the target object (there isn't one!), so it gives an error.

You need to do:

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

This way, the compiler knows how to add 2 - it knows the sizeof(char).

Eran
  • 387,369
  • 54
  • 702
  • 768
Baldrick
  • 11,712
  • 2
  • 31
  • 35
0

Please correct me if I'm wrong but as per my understanding, using a char* instead of a void* would have taken up 3 bytes for 3-digit numbers.

Yes, you are wrong, that would be the case if you were transmitting the numbers as chars. 'char*' is just a convenient way of referring to 8-bit values - and since you are receiving pairs of bytes, you could treat the destination memory are char's to do simple math. But it is fairly common for people to use 'char' arrays for network data streams.

I prefer to use something like BYTE or uint8_t to indicate clearly 'I'm working with bytes' as opposed to char or other values.

void* is a pointer to an unknown, more importantly, 0 sized type (void). Because the size is zero, offset math is going to result in zeros, so the compiler tells you it's invalid.

It is possible that your solution could be as simple as to receive the bytes from the network into a byte-based array. An int is 32 bits, 4 bytes. They're not "char" values, but quads of a 4-byte integer.

#include <cstdint>

uint8_t buffer[4];

Once you know you've filled the buffer, you can simply say

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

Whether this is correct will depend on whether the bytes are in network or host order. I'm guessing you'll probably need:

uint32_t integer = ntohl(*(static_cast<uint32*>(buffer)));
kfsone
  • 23,617
  • 2
  • 42
  • 74