Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么有些程序员习惯于使用长位移位,而不是直接赋值/将其存储为常量_C_Assembly_Bit Shift - Fatal编程技术网

C 为什么有些程序员习惯于使用长位移位,而不是直接赋值/将其存储为常量

C 为什么有些程序员习惯于使用长位移位,而不是直接赋值/将其存储为常量,c,assembly,bit-shift,C,Assembly,Bit Shift,请考虑下面的代码 一些RISC指令集将允许您按给定量进行移位,这很方便。例如,MIPS允许您提供shamt参数。其他指令集就不那么方便了。MSP430(16位-不是扩展指令)编译器需要将其呈现为对RLA伪指令的循环调用 因此,在某些情况下,这样做似乎没有“伤害”,但在其他情况下,似乎可以。这样长时间轮班有什么好处吗?因为从某种意义上讲,这似乎会降低代码的可移植性 X86或其他CISC机器是否会用它做一些我不知道的神奇事情 它更显式,而且由于它只涉及常量,因此肯定会在编译时而不是运行时进行计算,因

请考虑下面的代码

一些RISC指令集将允许您按给定量进行移位,这很方便。例如,MIPS允许您提供
shamt
参数。其他指令集就不那么方便了。MSP430(16位-不是扩展指令)编译器需要将其呈现为对
RLA
伪指令的循环调用

因此,在某些情况下,这样做似乎没有“伤害”,但在其他情况下,似乎可以。这样长时间轮班有什么好处吗?因为从某种意义上讲,这似乎会降低代码的可移植性


X86或其他CISC机器是否会用它做一些我不知道的神奇事情

它更显式,而且由于它只涉及常量,因此肯定会在编译时而不是运行时进行计算,因此最终生成的代码将完全相同。

更多选项以匹配文档。驱动代码的是什么,驱动风格的是什么


支持文件可能会说设置了第14位(范围为0到15),以下代码与此直接相关。注意
1它更具可读性,正如@jcaron所说,它将是相同的东西
毕竟。这是我编译成汇编的相关部分,甚至不是
经过优化,只需
-S

_isqrt:                                 ## @isqrt

[...]

Ltmp4:
        .cfi_def_cfa_register %rbp
        movw    %di, %ax
        movw    %ax, -2(%rbp)
        movw    $0, -4(%rbp)
        movw    $16384, -6(%rbp)        ## imm = 0x4000

16384
0x4000
1C有整数常量表达式,在翻译过程中便于计算。这就是为什么你可以这样做:

enum {
    foo_bit,
    bar_bit,
    baz_bit,
    foo_flag = 1 << foo_bit,
    bar_flag = 1 << bar_bit,
    baz_flag = 1 << baz_bit
  };
static unsigned int some_flags = bar_flag | baz_flag;
enum{
福比特,
巴鲁比特,
巴兹比特,

foo_flag=1大多数编译器都会进行常量折叠,所以表达式
1实际上我猜那是第15位。所以我的可读性参数中有一小部分…;@cdhowie的第14位或第15位取决于从1还是从0开始计数。这也是一场圣战。我从0开始计数,我的64位计算器应用程序也是如此,所以这对我来说都很好yway.NOTE对位运算使用有符号整数是危险的。对isqrt()使用有符号整数是疯狂的。注2:牛顿/拉尔夫斯顿对32位(无符号)整数进行4次迭代收敛,因此可以避免循环。我的+1让您获得了3000次代表。不客气。:(JK,这是您的全部。)@Jashaszun 3000不是一个令人印象深刻的数字。
1啊哈!所以答案是处理器根本没有左移!谢谢你的快速响应。你让我的头免于几分钟的额外抓挠。@Nick处理器正在左移。问题是什么时候:它在编译程序时做一次左移,而不是e每次程序都在运行。好吧,在我的例子中,是我的PC的GHz时钟X86处理器在运行,而不是我的小型低功耗MHz时钟uC。所以我应该更正确地说“我的目标处理器从来没有真正左移过”
16384,0x4000,1@chux是的,当然。但我的意思是,在这种情况下,在签署的简短声明前写下任何这些,都会导致同样的结果。@chux这在细节上有点疯狂,在我看来不需要提及,因为这(我的问题)只是为了展示一点集合来证明它是被评估的,当然我所说的与上下文相关,这里不需要关心符号(对于这些常量)。无论如何,谢谢你注意到它!我确实编辑了答案。非常好的示例和解释,邵!是的,谢谢,将它放在枚举中可以非常清楚地表明它是在运行时之前进行计算的。开关案例将使其更明显地表明,它们实际上得到了常数的计算…
case(bar|flag | baz|flag):
…technosaurus:我不知道为什么这会更明显。:)关于ICE,case和enum有相同的约束。也许你认为大多数人比enum约束更了解case约束。也许是这样;我不知道。
short bit = 0x4000;
int x = 1 << 14;  
int mask = 0x4000;
_isqrt:                                 ## @isqrt

[...]

Ltmp4:
        .cfi_def_cfa_register %rbp
        movw    %di, %ax
        movw    %ax, -2(%rbp)
        movw    $0, -4(%rbp)
        movw    $16384, -6(%rbp)        ## imm = 0x4000
enum {
    foo_bit,
    bar_bit,
    baz_bit,
    foo_flag = 1 << foo_bit,
    bar_flag = 1 << bar_bit,
    baz_flag = 1 << baz_bit
  };
static unsigned int some_flags = bar_flag | baz_flag;