Вы также можете рассмотреть использование memmove
в Git 2.14.x (3-й квартал 2017 г.)
См. коммит 168e635 (16 июля 2017 г.) и коммит 1773664, коммит f331ab9 , коммит 5783980 (15 июля 2017 г.) Рене Шарф (rscharfe
) .
(объединено Junio C Hamano - gitster
- in commit 32f9025 , 11 августа 2017 г.)
Используется вспомогательный макрос MOVE_ARRAY
, который вычисляет размер на основе указанного количества элементов для нас и поддерживает указатели NULL
, когда это число равно нулю.
Raw memmove(3)
вызовы с NULL
могут вызвать компилятор(с чрезмерным нетерпением) оптимизировать последующие NULL
проверки.
MOVE_ARRAY
добавляет безопасный и удобный помощник для перемещения потенциально перекрывающихся диапазонов записей массива.
Он выводит размер элемента, умножает автоматически и безопасно для получения размера в байтах, выполняет базовую проверку безопасности типа, сравнивая размеры элемента и в отличие от memmove(3)
он поддерживает NULL
указатели, если необходимо переместить 0 элементов.
#define MOVE_ARRAY(dst, src, n) move_array((dst), (src), (n), sizeof(*(dst)) + \
BUILD_ASSERT_OR_ZERO(sizeof(*(dst)) == sizeof(*(src))))
static inline void move_array(void *dst, const void *src, size_t n, size_t size)
{
if (n)
memmove(dst, src, st_mult(size, n));
}
Примеры :
- memmove(dst, src, (n) * sizeof(*dst));
+ MOVE_ARRAY(dst, src, n);
Используется макрос BUILD_ASSERT_OR_ZERO
, которая утверждает зависимость во время сборки, как выражение (где @cond
является условием времени компиляции, которое должно быть истинным).
Компиляция не будет выполнена, если условие не выполнено, илине может быть вычислено компилятором.
#define BUILD_ASSERT_OR_ZERO(cond) \
(sizeof(char [1 - 2*!(cond)]) - 1)
Пример:
#define foo_to_char(foo) \
((char *)(foo) \
+ BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0))