Vineet Menon
Vineet Menon

Reputation: 738

Does memcpy depend on the type of the source and destination pointers?

This code,

uint32_t length;
BYTE* message;
printf("Inspecting message with length %d and contents: ", length);
for(int i=0;i<length;i++)
    printf("%d ", message[i]);
printf("\n");
....
char* outbuff;
outbuff = (char*) malloc(sizeof(char) * length + sizeof(int));
uint32_t data_length = htonl(length);
memcpy(outbuff, &data_length , sizeof(int));
memcpy(outbuff + sizeof(uint32_t), message, length);

printf("Sending  outbuff over network with length %d and contents: ", length);
for(int i=0;i<length;i++)
    printf("%d ", outbuff[i]);
printf("\n");

doesn't faithfully copy data from message and length to outbuff. But as soon as I change the type of outbuff from char* to BYTE*, it works fine.

Any idea why it behaves so? The documentation doesn't help in this matter.

EDIT.1: Changed &length to &data_length. I manually typed the code instead of copying in SX.

EDIT.2: Code to print out the BYTE array.

Upvotes: 0

Views: 1296

Answers (3)

Nikhil Saxena
Nikhil Saxena

Reputation: 39

Doing memcpy() from BYTE* to char* may lead to wrap around range of char i.e. -127 to 127 due to BYTE being unsigned from 0 to 255.

For example, suppose we have:

BYTE uchArr[] = {12, 129, 250};
BYTE * ptr_uchArr = (BYTE*) malloc (sizeof(BYTE)*3);
memcpy(ptr_uchArr, &uchArr, sizeof(BYTE)*3);
//ptr_uchArr shall be {12, 129, 250} as intended...

And now we want to perform memcpy() from BYTE* to char*

char * ptr_chArr = (char*) malloc (sizeof(char)*3);
memcpy(ptr_chArr, ptr_uchArr, sizeof(BYTE)*3);
//ptr_chArr shall be {12, -127, -6} as a result of wrap around...

What if we perform the reverse i.e. memcpy() from char* to BYTE*:

memcpy(ptr_uchArr, ptr_chArr, sizeof(BYTE)*3);
//ptr_uchArr shall still be {12, 129, 250} as intended again as a result of wrap around...

Upvotes: 0

Peter - Reinstate Monica
Peter - Reinstate Monica

Reputation: 16026

I'm answering the new title question which I just edited in myself ;-).

The answer is a simple No.

The link in your question shows that memcpy()is declared as void *memcpy(void *dest, const void *src, size_t n);. Both pointer parameters are void pointers.

The standard draft lists conversions of any pointer to void * as a standard conversion (which does not need an explicit cast). Specifically, it states (emphasis by me):

A prvalue of type “pointer to cv T”, where T is an object type, can be converted to a prvalue of type “pointer to cv void”. The pointer value ([basic.compound]) is unchanged by this conversion.

This means that any object pointer you throw at it will be converted to a numerically identical void pointer before memcpy even sees it, and hence be treated identically.

Your problem must be elsewhere.

Upvotes: 3

xception
xception

Reputation: 4287

Just guessing here but I think you meant to use network byte ordering, hence the data_length attribution, but after it you still put the length into the buffer instead.

Your

memcpy(outbuff, &length, sizeof(int));

should have probably read

memcpy(outbuff, &data_length, sizeof(uint32_t));

Also you seem to be using int and uint32_t interchangeably. They're not, even on platforms where the size matches the one is signed while the other one is unsigned.

Upvotes: 1

Related Questions