Справочник реализация CRC32 вычисляет таблицу поиска во время выполнения:
/* Table of CRCs of all 8-bit messages. */
unsigned long crc_table[256];
/* Flag: has the table been computed? Initially false. */
int crc_table_computed = 0;
/* Make the table for a fast CRC. */
void make_crc_table(void)
{
unsigned long c;
int n, k;
for (n = 0; n < 256; n++) {
c = (unsigned long) n;
for (k = 0; k < 8; k++) {
if (c & 1) {
c = 0xedb88320L ^ (c >> 1);
} else {
c = c >> 1;
}
}
crc_table[n] = c;
}
crc_table_computed = 1;
}
Можете ли вы вычислить таблицу во время компиляции, тем самым избавившись от функции и флага состояния?
code-challenge
c++
compile-time
fredoverflow
источник
источник
Ответы:
Вот простое решение C:
crc32table.c
Он опирается на нестандартный
__COUNTER__
макрос, а также на семантику оценки, где__COUNTER__
оценивается перед передачей в качестве аргумента в макрос.Обратите внимание, что, поскольку
STEP
его аргумент оценивается дважды иCRC
использует восемь вложенных его вызовов, возникает небольшой комбинаторный взрыв в размере кода:Я проверил это в GCC 4.6.0 и Clang 2.8 на 32-битном Linux, и оба создали правильную таблицу.
источник
Основной цикл
можно преобразовать в мета-функцию:
Затем препроцессор генерирует 256 вызовов этой мета-функции (для инициализатора массива):
Если у вас установлен Boost, генерировать инициализатор массива немного проще:
Наконец, следующий тестовый драйвер просто выводит на консоль все элементы массива:
источник
Решение C ++ 0x
Работает на GCC (4.6.1) и Clang (багажник 134121).
источник
C >> 1
, не сдвигает ли отрицательные значения правильное неопределенное поведение? ;)C
unsigned long
D...
D
static unsigned long constexpr crc_table[] = { D... };
compute<>::crc_table[I]
C ++ 0x с
constexpr
. Работает на GCC4.6.1Затем вы можете использовать
crc_table.data[X]
во время компиляции, потому чтоcrc_table
естьconstexpr
.источник
Это моя первая метапрограмма :
Я "жестко запрограммировал" вызовы шаблона, который выполняет вычисления :)
источник
times
шаблонunsigned crc_table[] = { f<0>::value , f<0 + 1>::value , f<0 + 2>::value , f<0 + 2 + 1>::value , f<0 + 4>::value , f<0 + 4 + 1>::value , f<0 + 4 + 2>::value , f<0 + 4 + 2 + 1>::value , f<0 + 8>::value ,
с использованием препроцессора. Сборка занимает столько же времени, сколько и моя. Если вы хотите, вы можете прочитать этот последний абзац как «Я развернул внешний цикл». Там нет другого выбора в C ++ 03D
Это действительно ставит C ++ в позор, не так ли?
источник
eval
.C / C ++,
306295 байтРаботая в обратном порядке, мы получаем длинный беззнаковый массив с именем crc_table. Мы можем опустить размер массива, так как макросы гарантируют, что в массиве будет ровно 256 элементов. Мы инициализируем массив с 16 «строками» данных, используя 16 вызовов макроса R.
Каждый вызов R расширяется на четыре фрагмента (макрос F) из четырех констант (макрос K), что в сумме составляет 16 «столбцов» данных.
Макрос K - это развернутый цикл, индексированный k в коде из исходного вопроса. Он обновляет значение c восемь раз, вызывая макрос C.
Это решение на основе препроцессора использует довольно много памяти при расширении макроса. Я попытался сделать его немного короче, добавив дополнительный уровень макроразвития, и мой компилятор рванул. Приведенный выше код компилируется (медленно) с Visual C ++ 2012 и g ++ 4.5.3 под Cygwin (64-битная оперативная память Windows 7, 8 ГБ).
Редактировать:
Фрагмент выше составляет 295 байт, включая пробелы. После расширения всех макросов, кроме C, он увеличивается до 9 918 байт. По мере расширения каждого уровня макроса C размер быстро увеличивается:
Таким образом, к тому времени, когда все макросы были расширены, этот маленький 295-байтовый файл расширяется до более 2,7 мегабайт кода, который должен быть скомпилирован для генерирования исходного массива из 1024 байт (при условии 32-битных длинных значений без знака)!
Другое редактирование:
Я изменил макрос C, основанный на макросе из другого ответа, чтобы выжать дополнительные 11 байтов, и значительно уменьшил полный расширенный размер макроса. Хотя 2,7 МБ не так плохо, как 54 МБ (предыдущий конечный размер всего расширения макросов), он все еще значителен.
источник
Я бы изменил предыдущий ответ, заменив последние три строки:
Где crcByte - это его макрос K без запятой. Затем создайте саму таблицу с помощью:
И никогда не пропускайте размер массива, так как компилятор затем проверит, что у вас есть правильное количество элементов.
источник