- 论坛徽章:
- 0
|
本帖最后由 没本 于 2012-02-05 18:43 编辑
C++源程序里面通常会有些字符串,现在希望编译后生成的可执行文件不要包含这些字符串,而是在编译时转成其字符串的CRC32值。
- static uint32_t c01[] = { TO_CRC32("This is a string"), TO_CRC32("This is another string") };
- void f()
- {
- const uint32_t c02 = TO_CRC32("change me to CRC32");
- }
复制代码 要求只用C++编译器完成,不允许使用自制预处理程序修改源程序,以免影响源程序的可读性。
还是老规矩,一定时间内无人能解答我就公开答案。这次时间长点,16小时吧。
用了C++11的变长参数模板在编译时生成CRC32快查表,用了C++11的constexpr实现编译时计算的常量表达式函数TO_CRC32(),最后用传统的C/C++函数实现来作验证。
程序在g++ 4.6和clang 3.0下编译运行通过。有了这个,可以搞很多以前做不到的事情了,呵呵。
- $ cat crc32.cpp
- #include <cstdio>
- #include <cstdint>
- #include <cassert>
- #include <cstring>
- //首先利用变长参数模板实现编译时生成CRC32快查表
- template < uint32_t C, int K = 0 >
- struct crc32tabi {
- static uint32_t const v =
- crc32tabi < (C & 1) ? (0xedb88320L ^ (C >> 1)) : (C >> 1), K + 1 >::v;
- };
- template < uint32_t C >
- struct crc32tabi <C, 8 > {
- static uint32_t const v = C;
- };
- template < int N = 0, uint32_t ... D >
- struct crc32tab:crc32tab < N + 1, D ..., crc32tabi < N >::v > {
- };
- template < uint32_t ... D >
- struct crc32tab <256, D ... > {
- static uint32_t const crc32_table[sizeof ... (D)];
- };
- template < uint32_t ... D >
- uint32_t const crc32tab < 256, D ... >::crc32_table[sizeof ... (D)] = {
- D ...
- };
- //在这里实现编译时执行的常量表达式函数
- template < uint32_t N, uint32_t I = 1 >
- struct crc32_calc {
- static const uint32_t calc (const char (&s)[N]) {
- static uint32_t const C = crc32_calc < N, I + 1 >::calc (s);
- return crc32tab <>::crc32_table[(C >> 24) ^ s[N - I - 1]] ^ (C << 8);
- };
- };
- template < uint32_t N > struct
- crc32_calc <N, N > {
- static constexpr uint32_t calc (const char (&s)[N]) {
- return 0x4c11db7;
- };
- };
- template < uint32_t N >
- constexpr uint32_t TO_CRC32 (const char (&s)[N]) {
- return crc32_calc < N >::calc (s);
- }
- //用传统的C/C++实现来进行验证
- uint32_t crc32_table[256];
- void make_crc32_table (void) {
- uint32_t c;
- int n, k;
- for (n = 0; n < 256; n++) {
- c = (uint32_t) n;
- for (k = 0; k < 8; k++) {
- if (c & 1) {
- c = 0xedb88320L ^ (c >> 1);
- } else {
- c = c >> 1;
- }
- }
- crc32_table[n] = c;
- }
- }
- uint32_t crc32( const char *p, uint32_t len) {
- uint32_t sum = 0x4c11db7;
- while (len--)
- sum = crc32_table[(sum >> 24) ^ *p++] ^ (sum << 8);
- return sum;
- }
- #define STR01 "This is a string"
- #define STR02 "This is another string"
- static uint32_t c01[] =
- { TO_CRC32 (STR01), TO_CRC32 (STR02) };
- int main () {
- make_crc32_table ();
- for (int i = 0; i < 256; i++)
- assert( crc32tab <>::crc32_table[i] == crc32_table[i] );
- printf ("CRC Table check succeed.\n");
- printf ("help(crc32): %08X, %08X\n",
- TO_CRC32 ("help"), crc32("help",4));
- printf ("c01(p): %08X, %08X\n",
- c01[0], c01[1]);
- printf ("c01(f): %08X, %08X\n",
- crc32(STR01,strlen(STR01)),
- crc32(STR02,strlen(STR02)));
- return 0;
- }
- $ g++ -o crc32 -std=c++0x crc32.cpp
- $ ./crc32
- CRC Table check succeed.
- help(crc32): DC8AEE51, DC8AEE51
- c01(p): D577DEDA, DD55A5B6
- c01(f): D577DEDA, DD55A5B6
- $ clang++ -o crc32cl -std=c++0x crc32.cpp
- $ ./crc32cl
- CRC Table check succeed.
- help(crc32): DC8AEE51, DC8AEE51
- c01(p): D577DEDA, DD55A5B6
- c01(f): D577DEDA, DD55A5B6
- $
复制代码 |
|