【发布时间】:2014-01-16 14:29:58
【问题描述】:
我正在用 C (gcc) 编写一个应用程序,它会进行大量的字符串比较。总是一个带有一长串编译时常量字符串的未知/动态字符串。 所以我想我散列动态字符串并将生成的散列与常量字符串的预计算散列进行比较。
这样做我在一个函数(用于动态运行时字符串)和一个宏中有哈希算法,以便 gcc 在编译时评估哈希。
我知道了:
#define HASH_CALC(h, s) ((h) * 33 + *(s))
#define HASH_CALC1(s) (HASH_CALC(hash_calc_start, s))
#define HASH_CALC2(s) (HASH_CALC(HASH_CALC1(s), s + 1))
#define HASH_CALC3(s) (HASH_CALC(HASH_CALC2(s), s + 2))
#define HASH_CALC4(s) (HASH_CALC(HASH_CALC3(s), s + 3))
#define HASH_CALC5(s) (HASH_CALC(HASH_CALC4(s), s + 4))
//--> cut ... goes till HASH_CALC32
static const unsigned long hash_calc_start = 5381;
unsigned long hash_str (const char* c);
void func () {
//This string is not constant ... just in this case to show something
char dynStr = "foo";
unsigned long dynHash = hash_str (dynStr);
//gcc produces a cmp with a constant number as foo is hashed during compile-time
if (dynHash == HASH_CALC3("foo")) {
}
}
现在问题来了:
是否可以创建一个扩展为 HASH_CALCX(s) 的宏,其中 X 是传递给宏的常量字符串的长度?
//Expands to HASH_CALC3("foo")
if (dynHash == HASH_CALCX("foo")) {
}
//Expands to HASH_CALC6("foobar")
if (dynHash == HASH_CALCX("foobar")) {
}
我试过了,但它不起作用。
#define HASH_STRLEN(x) (sizeof(x)/sizeof(x[0])-1)
#define HASH_MERGE(x,y) x ## y
#define HASH_MERGE2(x,y) HASH_MERGE(x,y)
#define HASH_CALCX(s) (HASH_MERGE2(HASH_CALC, HASH_STRLEN(s))(s))
谢谢!
【问题讨论】:
-
没有必要。
strlen非常适合字符串常量,返回一个编译时常量。 -
@Damon Well ... #define HASH_CALCX(s) (HASH_MERGE2(HASH_CALC, strlen(s))(s)) 也不起作用,因为 strlen("") 没有展开。
-
hash_calc_start是如何定义的?#define hash_calc_start 0? -
其实是 static const unsigned long hash_calc_start = 5381;但是如果这对我的问题有帮助的话,将它定义为宏常量是没有问题的:-)
-
您是否曾尝试只调用散列函数而不是使用宏?如果函数定义在同一个翻译单元中,任何现代编译器都应该能够内联它并最终减少为一个常量。