Как скопировать память из источника, который не находится на выравнивании байтов (смещен) - PullRequest
5 голосов
/ 18 сентября 2010

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

Например, я хочу скопировать 10 байтов, начиная с 3-го бита в байте, и скопировать в указатель как обычно.

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

Спасибо

Ответы [ 3 ]

5 голосов
/ 18 сентября 2010

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

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

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

Если вы покопаетесь в исходном коде в инструменте сжатия или библиотеке, которая широко использует токены переменной ширины (zlib, MPEG, TIFF и JPEG - все на ум), вы, скорее всего, найдете пример кода, который обрабатывает ввод или выходной буфер как поток битов, о котором нужно будет подумать.

3 голосов
/ 18 сентября 2010

На x86 у вас самая маленькая единица, к которой у вас есть доступ, - это байт. Однако вы можете получить доступ к 4 байтам за раз и работать с 4 байтами за раз вместо одного байта. Для больших скоростей вы можете использовать pslldq ( SSE2 ). Конечно, убедитесь, что ваши копии выровнены для максимальной производительности.

0 голосов
/ 18 сентября 2010

Это решение, которое я кодировал и начал использовать.

void RightShiftMemCopy(uchar * pSource, uchar * pDest ,ushort len,uchar shiftOffset)
{
    ushort i=0;

    pDest+=(len-1);
    pSource+=(len-1);

    for(i=len-1;i != 0 ;--i)
    {
        *pDest = (*(pSource - 1) << 8 | *pSource) >> shiftOffset;

        --pDest;
        --pSource;
    }

    *pDest = *pSource >> shiftOffset;

}
...