C++编译器是否识别2的幂?

Van*_*ace 3 c++ hash assembly

我正在构建一个自定义哈希,我根据公式对字符串中的所有字母求和:

string[0] * 65536 + string[1] * 32768 + string[2] * 16384 + ...
Run Code Online (Sandbox Code Playgroud)

而且我遇到了一个问题,我是否应该将这些数字定义为int数组中的常量,如下所示:

const int MULTIPLICATION[] = {
    65536,
    32768,
    16384,
    8192,
    4096,
    2048,
    1024,
    512,
    256,
    128,
    64,
    32,
    16,
    8,
    4,
    2,
    1
}
Run Code Online (Sandbox Code Playgroud)

或者,也许我应该在计算哈希本身时生成这些数字(虽然由于它们尚未生成而可能会失去一些速度)?我需要数百万次计算这个哈希值,我希望编译器理解的主要内容是代替普通的MUL操作

MOV EBX, 8
MUL EBX
Run Code Online (Sandbox Code Playgroud)

它会的

SHL EAX, 3
Run Code Online (Sandbox Code Playgroud)

编译器是否理解如果我乘以2的幂来移位而不是通常的乘法?

另一个问题,我很确定当你用c ++编号*= 2时,它会移位.但只是为了澄清,是吗?


谢谢,我已经找到了如何在调试器中查看dissasembly.是的,如果您使用它,编译器确实理解移位

number *= 65536
Run Code Online (Sandbox Code Playgroud)

但是,如果你这样做,它会进行正常的乘法运算

number1 = 65536
number *= number1;
Run Code Online (Sandbox Code Playgroud)

Jon*_*art 5

试试吧!

你用的是什么编译器?您可以告诉大多数编译器在编译后保留中间文件,或者只编译(而不是汇编),这样您就可以实际查看它生成的汇编代码.

你可以看到我的另一个问题,这就是我所做的.

例如,在gcc中,-S标志表示"仅编译".并-masm=intel生成更易读的程序集,IMO.


编辑

总而言之,我认为以下是您正在寻找的算法(未经测试):

// Rotate right by n bits
#define ROR(a, n)   ((a >> n) | (a << (sizeof(a)*8-n)))


int custom_hash(const char* str, int len) {
    int hash = 0;
    int mult = 0x10000;  // 65536, but more obvious

    for (int i=0; i<len; i++) {
        hash += str[i] * mult;
        mult = ROR(mult, 1);    
    }

    return mult;
}
Run Code Online (Sandbox Code Playgroud)

首先,你没有指定当你有超过16个字符时会发生什么(乘数是多少?)所以在这个实现中,我使用了一个按位旋转.86具有逐位循环指令(rorrol分别旋转左,右).但是,C没有提供表达旋转操作的方法.所以我定义了ROR为你做旋转的宏.(了解它的工作原理留给读者练习!)

在我的循环中,我像你一样在0x10000(65536)开始乘数.循环的每次迭代,我将乘数右旋一位.这基本上将它除以2,直到达到1,之后变为0x80000000.

  • @VanillaFace在VC++上,选项是`/ Fa`,后跟可选文件名(没有空格).在Visual Studios中,在源文件的属性中,在C/C++&rarr; Output Files下,有一个Assembler Output和ASM List Location的条目. (2认同)