Nano Hash - криптовалюты, майнинг, программирование

Как и когда использовать memmove в C?

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

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

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

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

28.01.2012


Ответы:


1
  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) означает «получить размер элемента массива»)

28.01.2012
  • Я хочу удалить элемент из массива и сдвинуть влево элемент того же массива. 28.01.2012
  • Обратите внимание, что только memcpy может быть быстрее для неперекрывающихся данных; использование memcpy также служит для документирования того, что вы копируете между отдельными объектами, а не перемещаете элементы внутри одного объекта массива. 28.01.2012
  • Хорошо спасибо. Я понимаю разницу. Grazie mille из Италии в. ;) 28.01.2012
  • @Kyrol: пожалуйста; tra l'altro, tanta optima per l'avatar dei Pink Floyd. :) 28.01.2012
  • @Kyrol: Это определенно похоже на работу для memmove(). 28.01.2012
  • Когда я изначально писал эту функциональность в своей программе (не обращаясь ни к чему, кроме документации memmove), я кодировал массив указателей с изменяющимся размером. Оказывается, я забыл & перед myarray[i] при использовании метода индекса. Излишне говорить, что все закончилось плохо. :] 19.06.2013

  • 2

    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.

    28.01.2012
  • а если src и dst - это один и тот же массив ?? потому что сомневаюсь, придется ли мне удалить элемент и сдвинуть влево остальные элементы после удаленного. 28.01.2012
  • @Kyrol: все еще с примером char src[1024] = {0}. memcpy(src, src + 512, 512); тот же объект, но регионы не перекрываются: это нормально. Но memcpy(src + 256, src + 512, 512); области перекрываются, это не нормально, используйте вместо этого memmove. 28.01.2012
  • Стоит отметить, что memcpy быстрее, чем memmove, только на один оператор if 28.01.2012
  • @SethCarnegie, да, если вызывается C-версия memcpy. Некоторые встроенные команды быстрой сборки memmove не могут быть выполнены с теми же инструкциями MCU, что и memcpy. 28.01.2012
  • @SethCarnegie: Если реализация гарантирует, что выражение типа (p>q) никогда не сделает ничего, кроме 1 или 0, даже если p и q указывают на несвязанные области памяти, тогда она может реализовать memmove(), чтобы потребовать только один дополнительный if. Учитывая char *p=malloc(16), q[16];, выражение (p>q) может делать что угодно (например, неопределенное поведение). Несмотря на то, что для любых действительных указателей источника и назначения будет работать либо восходящий цикл, либо нисходящий цикл, нет переносимого способа определить, какой из них будет безопасным. 06.12.2014

  • 3

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

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

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

    Только 1_?

    28.01.2012
  • Что вы не поняли по поводу моего второго вопроса ?? Я пытаюсь объяснить мне лучше. 28.01.2012
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

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

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..