Зависит ли memcpy от типа указателей источника и назначения? - PullRequest
0 голосов
/ 06 ноября 2019

Этот код,

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

, не позволяет достоверно копировать данные из сообщения и его длину в исходящие данные. Но как только я меняю тип outbuff с char * на BYTE *, он работает нормально.

Есть идеи, почему он так себя ведет? Документация не помогает в этом вопросе.

EDIT.1: изменено &length на &data_length. Я вручную набрал код вместо копирования в SX.

EDIT.2: Код для распечатки массива BYTE.

Ответы [ 3 ]

2 голосов
/ 06 ноября 2019

Я отвечаю на новый заглавный вопрос, который я только что отредактировал в себе; -).

Ответ прост: Нет.

Ссылка в вашемВопрос показывает, что memcpy() объявлено как void *memcpy(void *dest, const void *src, size_t n);. Оба параметра указателя являются пустыми указателями.

Стандартный черновик перечисляет преобразования любого указателя в void * как стандартное преобразование (для которого не требуется явное приведение). В частности, в нем указывается (выделено мной):

Значение типа «указатель на cv T», где T - тип объекта, может быть преобразовано в значение типавведите «указатель на cv void». Значение указателя ([basic.compound]) не изменяется при этом преобразовании.

Это означает, что любой указатель объекта, который вы на него набрасываете, будет преобразован в численно идентичный указатель void. прежде чем memcpy даже увидит его, и, следовательно, будет обрабатываться одинаково.

Ваша проблема должна быть в другом месте.

1 голос
/ 06 ноября 2019

Просто угадайте здесь, но я думаю, что вы хотели использовать сетевое упорядочение байтов, отсюда и атрибуцию data_length, но после этого вы все равно поместили length в буфер.

Ваш

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

вероятно должен был прочитать

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

Также вы, кажется, используете int и uint32_t взаимозаменяемо. Это не так, даже на платформах, размер которых совпадает с тем, который подписан, а другой - без знака.

0 голосов
/ 07 ноября 2019

Выполнение memcpy() с BYTE* до char* может привести к переносу вокруг диапазона char, то есть от -127 до 127, из-за того, что BYTE будет без знака от 0 до 255.

Напримерпредположим, что у нас есть:

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...

И теперь мы хотим выполнить memcpy() с BYTE* до 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...

Что если мы выполним обратное, то есть memcpy()от char* до 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...
...