Как использовать и когда хорошо использовать memmove в C? - PullRequest
12 голосов
/ 28 января 2012

У меня есть два сомнения по поводу использования memmove () :

  • Когда предпочтительно использовать эту функцию вместо использования другой функции (то есть созданной собственной функции)? Я не уверен, что правильно понял.
  • Сигнатура функции: void * memmove (void * dest, const void * src, size_t n) . Если у меня есть простой массив arr [N] , как я могу поместить его в вызываемую функцию? arr [N] или & arr [N]? Разница в том, если массив объявлен с начальным размером или как указатель? У меня есть это сомнение, потому что я видел много примеров, где используются оба.

Надеюсь, я хорошо объяснил свои сомнения.

edit: мне нужно удалить элемент из массива, а затем я хочу сместить следующие элементы удаленного элемента влево.

Ответы [ 3 ]

17 голосов
/ 28 января 2012
  1. memmove может быть быстрее, но, вероятно, никогда не будет медленнее, чем ваша собственная функция для копирования данных (обычно это кодируется в тщательно созданной сборке, чтобы перемещать объекты наиболее эффективным способом из текущей архитектуры);
  2. это зависит от того, что вы хотите сделать с этим массивом ... если вы хотите скопировать его содержимое в другой массив, то достаточно будет arr (и, как параметр длины, вы должны сделать sizeof(*arr)*N, где N - это количество элементов для копирования).

Кстати, если источник и место назначения и копия не перекрываются, memcpy может быть быстрее.

Я хочу удалить элемент из массива и сдвинуть влево элемент этого же массива.

int arr[N];
/* ... */
/* Let's say you want to remove the element i (error checking on i omitted) */
memmove(arr+i, arr+i+1, (N-i-1)*sizeof(*arr));
/* or, if you prefer array indexing over pointer arithmetics: */
memmove(&arr[i], &arr[i+1], (N-i-1)*sizeof(*arr));

(sizeof(*arr) означает «получить размер элемента массива»)

5 голосов
/ 28 января 2012

memmove похоже на memcpy, за исключением того, что целевой и исходный массив могут перекрываться.

С memcpy вы обещаете, что регионы не перекрываются, что позволяет реализации выполнить некоторые дополнительные оптимизации. Так что memcpy может быть быстрее, чем memmove.

Функция memmove принимает целевой аргумент void * и исходный аргумент const void *. Это означает, что вы можете вызывать функцию с целевым и исходным аргументом типа массива, поскольку они будут преобразованы в типы указателей. А так как вы можете назначить любые неквалифицированные типы указателей объектов на void * или const void *, вам не понадобится приведение при вызове функции.

char src[1024] = {0};
char dst[1024];

memmove(dst, src, sizeof dst);
/* src and dst don't overlap you should choose memcpy instead */
memcpy(dst, src, sizeof dst);

Теперь обычно лучше использовать memcpy или memmove, чем кодировать собственную функцию. Например, в glibc, в зависимости от набора команд MCU и размера для копирования, memcpy может быть заменен компилятором с некоторыми версиями быстрой встроенной сборки memcpy.

0 голосов
/ 28 января 2012

Когда предпочтительно использовать эту функцию вместо использования другой функции (то есть созданной собственной функции)

Это быстрее, чем "созданная собственная функция".

подпись функции void * memmove (void * dest, const void * src, size_t n). Если у меня есть простой массив arr [N], как я могу поместить его в вызываемую функцию? arr [N] или & arr [N]

Просто arr?

...