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