Подтвердить что ты не робот

Может memcpy или memmove возвращать другой указатель, чем dest?

Функция memmove определяется следующим образом:

void *memmove(void *dest, const void *src, size_t n);

На странице руководства Linux говорится:

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Функция memmove() возвращает указатель на dest.

Почему не функция, определенная как void memmove(…), когда она всегда возвращает один из входных параметров? Может ли возвращаемое значение отличаться от dest?

Или это возвращаемое значение всегда всегда dest, и только что сделано, чтобы иметь возможность составлять функцию в некоторых творческих способах?

4b9b3361

Ответ 1

memmove никогда не вернет ничего, кроме dest.

Возвращение dest, в отличие от создания memmove void, полезно, когда первый аргумент является вычисленным выражением, поскольку он позволяет избежать вычисления одного и того же значения вверх и хранения его в переменной. Это позволяет сделать в одной строке

void *dest = memmove(&buf[offset] + copiedSoFar, src + offset, sizeof(buf)-offset-copiedSoFar);

что вам в противном случае нужно было бы сделать на двух строках:

void *dest = &buf[offset] + copiedSoFar;
memmove(dest, src + offset, sizeof(buf)-offset-copiedSoFar);

Ответ 2

Согласно C11, глава §7.24.2.1 и §7.24.2.2

void *memcpy(void * restrict s1, const void * restrict s2, size_t n);

[...] Функция memcpy возвращает значение s1.

и

void *memmove(void *s1, const void *s2, size_t n);

[...] Функция memmove возвращает значение s1.

Таким образом, функции всегда возвращают указатель на буфер назначения, который по дизайну.

Теперь, перейдя к части почему, многие функции разработаны таким образом, чтобы сделать цепочку вызовов функций возможной. Таким образом, вы можете вызвать вызов memmove() в качестве аргумента другой функции, где скопированное значение (т.е. Указатель на dest) будет полезным.

Например, вы можете написать более короткий

 puts(memmove(dest_buffer, src_buffer, welcome_message_size));

вместо более длинного

 memmove(dest_buffer, src_buffer, welcome_message_size);
 puts(dest_buffer);

Ответ 3

Идиома возврата точного значения одного из аргументов (типа указателя) существует для поддержки "цепных" вызовов функций (также см. strcpy, strcat и т.д.). Это позволяет вам писать некоторый повторяющийся код в виде выражения одного выражения вместо того, чтобы разбивать его на несколько операторов. Например

char buffer[1024];
printf("%s\n", strcat(strcat(strcpy(buffer, "Hello"), " "), "World"));

struct UserData data_copy;
some_function(memcpy(&data_copy, &original_data, sizeof original_data));

Даже если вам не нравится этот стиль организации кода и предпочитает делать то же самое с помощью нескольких операторов, накладные расходы на возврат значения [ненужного] указателя практически отсутствуют.

Можно даже сказать, что значение этой идиомы немного увеличилось после введения сложных C-образных литералов. С составными lterals эта самая идиома позволяет писать один и тот же код без введения именованной промежуточной переменной

printf("%s\n", strcat(strcat(strcpy((char [1024]) { 0 }, "Hello"), " "), "World!"));

some_function(memcpy(&(struct UserData) { 0 }, &original_data, sizeof original_data));

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