# 在编译时计算CRC32表[关闭]

16

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;
}
``````

2

John Dvorak 2014年

Answers:

12

crc32table.c

``````#if __COUNTER__ == 0

/* Initial setup */
#define STEP(c) ((c)>>1 ^ ((c)&1 ? 0xedb88320L : 0))
#define CRC(n) STEP(STEP(STEP(STEP(STEP(STEP(STEP(STEP((unsigned long)(n)))))))))
#define CRC4(n) CRC(n), CRC(n+1), CRC(n+2), CRC(n+3)

/* Open up crc_table; subsequent iterations will fill its members. */
const unsigned long crc_table[256] = {

/* Include recursively for next iteration. */
#include "crc32table.c"

#elif __COUNTER__ < 256 * 3 / 4

/* Fill the next four CRC entries. */
CRC4((__COUNTER__ - 3) / 3 * 4),

/* Include recursively for next iteration. */
#include "crc32table.c"

#else

/* Close crc_table. */
};

#endif
``````

``````\$ cpp crc32table.c | wc -c
4563276
``````

R. Martinho Fernandes

9

``````for (k = 0; k < 8; k++) {
if (c & 1) {
c = 0xedb88320L ^ (c >> 1);
} else {
c = c >> 1;
}
}
``````

``````template <unsigned c, int k = 8>
struct f : f<((c & 1) ? 0xedb88320 : 0) ^ (c >> 1), k - 1> {};

template <unsigned c>
struct f<c, 0>
{
enum { value = c };
};
``````

``````#define A(x) B(x) B(x + 128)
#define B(x) C(x) C(x +  64)
#define C(x) D(x) D(x +  32)
#define D(x) E(x) E(x +  16)
#define E(x) F(x) F(x +   8)
#define F(x) G(x) G(x +   4)
#define G(x) H(x) H(x +   2)
#define H(x) I(x) I(x +   1)
#define I(x) f<x>::value ,

unsigned crc_table[] = { A(0) };
``````

``````#include <boost/preprocessor/repetition/enum.hpp>

#define F(Z, N, _) f<N>::value

unsigned crc_table[] = { BOOST_PP_ENUM(256, F, _) };
``````

``````#include <cstdio>

int main()
{
for (int i = 0; i < 256; ++i)
{
printf("%08x  ", crc_table[i]);
}
}
``````

6

C ++ 0x解决方案

``````template<unsigned long C, int K = 0>
struct computek {
static unsigned long const value =
computek<(C & 1) ? (0xedb88320L ^ (C >> 1)) : (C >> 1), K+1>::value;
};

template<unsigned long C>
struct computek<C, 8> {
static unsigned long const value = C;
};

template<int N = 0, unsigned long ...D>
struct compute : compute<N+1, D..., computek<N>::value>
{ };

template<unsigned long ...D>
struct compute<256, D...> {
static unsigned long const crc_table[sizeof...(D)];
};

template<unsigned long...D>
unsigned long const compute<256, D...>::crc_table[sizeof...(D)] = {
D...
};

/* print it */
#include <iostream>

int main() {
for(int i = 0; i < 256; i++)
std::cout << compute<>::crc_table[i] << std::endl;
}
``````

fredoverflow 2011年

fredoverflow

@弗雷德，你是对的。我还将做`C`一个`unsigned long`。常量数组定义为通过pack扩展进行初始化`D...``D`是非类型模板参数包。一旦GCC支持它，您也可以使用声明该数组在类中`static unsigned long constexpr crc_table[] = { D... };`，但是GCC尚未解析括号内的类初始化器。好处是`compute<>::crc_table[I]`可以在代码的后面的常量表达式中使用。
Johannes Schaub-litb 2011年

5

C ++ 0x和`constexpr`。适用于GCC4.6.1

``````constexpr unsigned long computek(unsigned long c, int k = 0) {
return k < 8 ? computek((c & 1) ? (0xedb88320L ^ (c >> 1)) : (c >> 1), k+1) : c;
}

struct table {
unsigned long data[256];
};

template<bool> struct sfinae { typedef table type; };
template<> struct sfinae<false> { };

template<typename ...T>
constexpr typename sfinae<sizeof...(T) == 256>::type compute(int n, T... t) {
return table {{ t... }};
}

template<typename ...T>
constexpr typename sfinae<sizeof...(T) <= 255>::type compute(int n, T... t) {
return compute(n+1, t..., computek(n));
}

constexpr table crc_table = compute(0);

#include <iostream>

int main() {
for(int i = 0; i < 256; i++)
std::cout << crc_table.data[i] << std::endl;
}
``````

4

``````#include <cassert>
#include <cstddef>

template <std::size_t N, template <unsigned long> class T, unsigned long In>
struct times : public T<times<N-1,T,In>::value> {};

template <unsigned long In, template <unsigned long> class T>
struct times<1,T,In> : public T<In> {};

template <unsigned long C>
struct iter {
enum { value = C & 1 ? 0xedb88320L ^ (C >> 1) : (C >> 1) };
};

template <std::size_t N>
struct compute : public times<8,iter,N> {};

unsigned long crc_table[] = {
compute<0>::value,
compute<1>::value,
compute<2>::value,
// .
// .
// .
compute<254>::value,
compute<255>::value,
};

/* Reference Table of CRCs of all 8-bit messages. */
unsigned long reference_table[256];

/* Flag: has the table been computed? Initially false. */
int reference_table_computed = 0;

/* Make the table for a fast CRC. */
void make_reference_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;
}
}
reference_table[n] = c;
}
reference_table_computed = 1;
}

int main() {
make_reference_table();
for(int i = 0; i < 256; ++i) {
assert(crc_table[i] == reference_table[i]);
}
}
``````

1

+1用于测试和`times`模板
fredoverflow 2011年

@Matthew：只有C ++ 03，别无选择。您可以像Fred一样使用预处理器，但这不会缩短编译时间。显然，他的预处理器使他的解决方案感到窒息：）
R. Martinho Fernandes

@Matthew的重点是在编译时实际进行计算，而不是对其进行硬编码。弗雷德的答案生成了这种形式的数组：`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 ++ 03中没有其他选择
R. Martinho Fernandes

Matthew阅读

3

# d

``````import std.stdio, std.conv;

string makeCRC32Table(string name){

string result = "immutable uint[256]"~name~" = [ ";

for(uint n; n < 256; n++){
uint c = n;
for(int k; k < 8; k++)
c = (c & 1) ? 0xedb88320L ^ (c >> 1) : c >>1;
result ~= to!string(c) ~ ", ";
}
return result ~ "];";
}

void main(){

/* fill table during compilation */
mixin(makeCRC32Table("crc_table"));

/* print the table */
foreach(c; crc_table)
writeln(c);
}
``````

2

R. Martinho Fernandes

Martin Nowak

3

# C / C ++，306 295字节

``````#define C(c)((c)>>1^((c)&1?0xEDB88320L:0))
#define K(c)(C(C(C(C(C(C(C(C(c))))))))),
#define F(h,l)K((h)|(l+0))K((h)|(l+1))K((h)|(l+2))K((h)|(l+3))
#define R(h)F(h<<4,0)F(h<<4,4)F(h<<4,8)F(h<<4,12)
unsigned long crc_table[]={R(0)R(1)R(2)R(3)R(4)R(5)R(6)R(7)R(8)R(9)R(10)R(11)R(12)R(13)R(14)R(15)};
``````

R的每次调用都会扩展为四个常量（宏K）的四个片段（宏F），总共有16个“列”数据。

1. 25,182
2. 54,174
3. 109,086
4. 212,766
5. 407,838
6. 773,406
7. 1,455,390
8. 2,721,054

Ilmari Karonen 2012年

CasaDeRobison 2012年

3

``````#define crc4( x)    crcByte(x), crcByte(x+1), crcByte(x+2), crcByte(x+3)
#define crc16( x)   crc4(x), crc4(x+4), crc4(x+8), crc4(x+12)
#define crc64( x)   crc16(x), crc16(x+16), crc16(x+32), crc16(x+48)
#define crc256( x)  crc64(x), crc64(x+64), crc64(x+128), crc64(x+192)
``````

``````static const unsigned long crc32Table[256] = { crc256( 0)};
``````

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.