2010-06-30 3 views
2

Я прочитал статью Optimizing Memcpy improves speed, у меня есть вопрос о алгоритме с измененным GNU, я получаю сообщение об ошибке, когда код src & 0xFFFFFFFC, src является указателем на пустоту, может ли он быть левым операнд для '&'? Я что-то пропустил?Вопрос о модифицированном алгоритме GNU

Благодаря

Ошибка 1 Ошибка C2296: '&': недопустимый, левый операнд имеет тип 'константный недействительным *'

void * memcpy(void * dst, void const * src, size_t len) 
{ 
    long * plDst = (long *) dst; 
    long const * plSrc = (long const *) src; 
    if (!(src & 0xFFFFFFFC) && !(dst & 0xFFFFFFFC)) 
    { 
     while (len >= 4) 
    { 
      *plDst++ = *plSrc++; 
      len -= 4; 
     } 
    } 
    char * pcDst = (char *) plDst; 
    char const * pcSrc = (char const *) plSrc; 
    len += 4; 
    while (len--) 
    { 
     *pcDst++ = *pcSrc++; 
    } 
    return (dst); 
} 
+0

Вы знаете, GCC на ПК, чтобы понять базовое * memcpy * определение достаточно хорошо, чтобы оно выдавало код для записи longs за раз, а double-longs, если вы скажете, что он может использовать MMX. –

ответ

1

Вы можете Bitmask указатели - это законная операция, если вы знаете, что ты делаешь.

Прежде всего, убедитесь, что ваш компилятор не в режиме C++ (поскольку, как представляется, вы используете MSVC++) - это должно быть предупреждение в C, а не ошибка.

Во-вторых, 0xFFFFFFFC является целым числом - вы должны сделать соответствующий отбор для рассматриваемой операции (введите тип указателя).

В-третьих, я ожидаю, что ваш компилятор/libc уже имеет фантастическую реализацию memcpy - используйте встроенную версию, а не свою собственную версию. Компиляторы выполняют некоторые обманки с помощью C и стандартных библиотечных функций и могут даже встроить и развернуть петли memcpy. Когда вы делаете свой собственный memcpy, этот обман обычно не выполняется.

+0

Спасибо theatrus, я просто хочу найти более эффективный способ сделать передачу данных с помощью memcpy, и я думаю, что нет смысла делать src & 0xFFFFFFFC. – Blurmylife

+0

Идея состоит в том, чтобы выровнять записи на 32-битных границах. –

+1

В дополнение к этим комментариям: записи, выровненные по 32-битным границам, часто намного быстрее, чем записи, которые не являются. Запись выровненного 32-битного фрагмента часто намного быстрее, чем запись 4 байтов в отдельности. Все это зависит от процессора, здесь мы, скорее всего, подразумеваем какую-то вещь на основе x86, хотя это справедливо для многих (не обязательно всех) архитектур. – Thanatos

0

Я читал подобную статью в http://www.eetimes.com/design/embedded/4024961/Optimizing-Memcpy-improves-speed/ и ту часть, которая кажется мне неправильной является то, что

if (!(src & 0xFFFFFFFC) && !(dst & 0xFFFFFFFC)) 

не проверяет совмещенные указатели.

например, если src равен 0x13 (нечетный), то src & 0xFFFFFFFC - 0x10. ! (0x10) равно 0, так что если сбой. хорошо.

если src выровнено, скажем 0x14, то src & 0xFFFFFFFC - 0x14. ! (0x14) равно 0, так что если сбой. упс.

Я думаю, что это уместно проверить:

if (!(src & 0x3) && !(dst & 0x3)) { 
    // pointers are aligned, copy in 32 bit chunks 
    .... 
} 

, и я также не вижу цель в Len + = 4; , но я предполагаю, что исходный вопрос был всего лишь ошибкой компиляции, поэтому весь этот отклик является отвлеченным, и, возможно, я неправильно понял, как он должен работать. (и я согласен с оригинальным ответом, просто используйте то, что приходит в библиотеку).

1

Не уверен, как это долгое время оставалось без ответа. Стандарт C действительно не может быть яснее по этому вопросу C99 §6.5.10 (побитовое И оператор):

Ограничения

Каждый из операндов должен иметь целочисленный тип.

Таким образом, вы должны гипса указателей на целые числа, прежде чем они могут быть использованы в качестве операндов &; в частности, вы должны отнести их к intptr_t (или uintptr_t), для которых стандарт гарантирует, что любой действительный указатель на void может быть преобразован в этот тип, а затем преобразован обратно в указатель на void, а результат будет сравняться с исходным указателем "

#include <stdint.h> 
... 
if ((intptr_t)src & 3) { 
    // src does not have 4 byte alignment 
} 

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

Смежные вопросы