.two {
position: fixed;
}
代码块在未使用但不受支持的体系结构中的行为是什么?例如,如果我在ARM上编译以下代码,会发生什么情况
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="position: fixed;">1</div>
<div class="two">2</div>
<div></div>
这是有效的C ++吗?代码会编译吗?标准是否对这种情况有任何说明?
答案 0 :(得分:5)
这取决于如何处理。来自[dcl.asm]
asm
声明的格式为asm-definition: attribute-specifier-seq opt asm ( string-literal ) ;
asm
声明是有条件支持的; 其含义是实现定义的。 asm定义中的可选attribute-specifier-seq与asm声明有关。 [注:通常,它用于将信息通过实现传递给汇编器。 —尾注]
强调我的
也就是说,您可以将代码放入#if #endif
中,使用SFINAE或使用if constexpr
。如果不满足条件,所有这些都将删除代码。
答案 1 :(得分:2)
是的,只要false
绝对是一个编译时常量,就可以在gcc和clang上使用。它将无法在完全不支持asm("");
的MSVC等编译器上进行编译。
不过,我不建议这样做。使用预处理器进行特定于拱和特定于实现的代码选择更为正常。
ISO C ++基本上没有什么可说的。 asm
是特定于实现的扩展,因此,即使在死代码中,实现也可以自由拒绝未汇编的asm。但是问题是我们实际使用的编译器是否像这样。
唯一有意义的问题是您关心的实际编译器会发生什么。
例如,在MSVC上,不支持asm("");
语法,无论字符串文字的内容如何。因此,到处都是编译时的语法错误。 您不能使用if(false){}
保护甚至无法编译的代码,就像在模板元编程中那样(不幸的是)一样。
在支持GNU扩展的编译器(最广泛使用的ISO C或C ++扩展,其中包括asm("")
样式的语法)上,让我们来看一下{{3 }} 。
我之所以选择on the Godbolt compiler explorer,是因为它是一条有效指令,不需要任何输入或输出操作数,因为它不会修改任何寄存器。而且与nop
之类的东西不同,它不会在非x86上汇编。 (volatile
对于mfence
是隐式的,没有输出操作数。)
void nobarrier() {
//int condition = 0; if(condition) // wouldn't work at -O0
if(false) {
// only an error with MSVC
asm("mfence" ::: "memory");
}
}
#ifdef UNCONDITIONAL
void barrier() {
// gcc compiles separately from assembling
// clang/LLVM's built-in assembler chokes at compile time
asm("mfence" ::: "memory");
}
#endif
即使禁用优化,GCC和clang甚至都不会尝试在asm()
内组装if(false)
语句。
当然,-O0
阻止他们将int cond=0;
if(cond){}
始终视为错误,因为为了进行一致的调试,它们使asm假定每个变量在内存中被(由调试器)修改,每个陈述。 (所有存储/重新加载的部分原因是未优化的代码如此之慢)。
使用ARM或AArch64 gcc,nobarrier()
可以很好地进行编译,汇编成的asm也可以。例如
@ gcc7.2 -O3 for ARM32. Similar output with -O0
nobarrier():
bx lr
GCC甚至没有尝试解析asm
模板的内容,因此它将为AArch64 编译 barrier()
,但是它包含的指令不会组装。
@ gcc6.3 -O0 -DUNCONDITIONAL
barrier():
mfence
nop
ret
如果您关心编译和汇编之间的区别,那么clang就不同了。
clang6.0 -O0 -target mips -DUNCONDITIONAL
说
<source>:13:9: error: unknown instruction
asm("mfence" ::: "memory");
^
<inline asm>:1:2: note: instantiated into assembly here
mfence
^
1 error generated.
Compiler returned: 1
如果您只关心C ++->目标文件,而不关心.s
asm源输出,则这无关紧要。为此,它的行为与gcc相同。 if(false)
确实使用非MIPS指令保护了asm
语句,使其不会被解析:
@ clang6.0 -O0 -target mips
nobarrier(): # @nobarrier()
addiu $sp, $sp, -8
sw $fp, 4($sp) # 4-byte Folded Spill
move $fp, $sp
move $sp, $fp
lw $fp, 4($sp) # 4-byte Folded Reload
addiu $sp, $sp, 8
jr $ra
nop