我知道C++ 中的"未定义行为"几乎可以让编译器做任何想做的事情.但是,我遇到了让我感到惊讶的崩溃,因为我认为代码足够安全.
在这种情况下,真正的问题仅发生在使用特定编译器的特定平台上,并且仅在启用了优化时才发生.
我尝试了几件事来重现问题并将其简化到最大程度.这是一个名为的函数的摘录Serialize,它将获取bool参数,并将字符串true或复制false到现有的目标缓冲区.
如果bool参数是未初始化的值,那么这个函数是否会在代码审查中,没有办法告诉它实际上可能会崩溃?
// Zero-filled global buffer of 16 characters
char destBuffer[16];
void Serialize(bool boolValue) {
// Determine which string to print based on boolValue
const char* whichString = boolValue ? "true" : "false";
// Compute the length of the string we selected
const size_t len = strlen(whichString);
// Copy string into destination buffer, which is zero-filled (thus already null-terminated)
memcpy(destBuffer, whichString, len);
}
Run Code Online (Sandbox Code Playgroud)
如果使用clang 5.0.0 +优化执行此代码,它将/可能崩溃.
boolValue ? "true" …
使用switch语句与使用if30个unsigned枚举的语句的最佳实践是什么,其中大约10个具有预期的操作(目前是相同的操作).需要考虑性能和空间,但并不重要.我已经抽象了代码片段,所以不要因为命名惯例而讨厌我.
switch 声明:
// numError is an error enumeration type, with 0 being the non-error case
// fire_special_event() is a stub method for the shared processing
switch (numError)
{
case ERROR_01 : // intentional fall-through
case ERROR_07 : // intentional fall-through
case ERROR_0A : // intentional fall-through
case ERROR_10 : // intentional fall-through
case ERROR_15 : // intentional fall-through
case ERROR_16 : // intentional fall-through
case ERROR_20 :
{
fire_special_event();
}
break;
default:
{ …Run Code Online (Sandbox Code Playgroud) 以下所有说明都做同样的事情:设置%eax为零.哪种方式最佳(需要最少的机器周期)?
xorl %eax, %eax
mov $0, %eax
andl $0, %eax
Run Code Online (Sandbox Code Playgroud) 我正在阅读Agner Fog的" 用C++优化软件 "(特定于英特尔,AMD和威盛的x86处理器),它在第34页说明
布尔变量存储为8位整数,值0表示false,1表示true.布尔变量是超定的,因为所有具有布尔变量作为输入的运算符检查输入是否具有除0或1之外的任何其他值,但是具有布尔值作为输出的运算符不能产生除0或1之外的其他值.布尔变量作为输入效率低于必要的效率.
这今天仍然适用于编译器吗?你能举个例子吗?作者说
如果确定操作数没有除0和1之外的其他值,则可以使布尔运算更有效.编译器没有做出这样的假设的原因是变量可能具有其他值,如果它们是未初始化或来自不明来源.
这是否意味着如果我拿一个函数指针bool(*)()作为示例并调用它,那么对它的操作会产生效率低下的代码?或者是通过取消引用指针或从引用读取然后对其进行操作来访问布尔值的情况?
x86-64 System V ABI(用于除Windows之外的所有内容)过去常常访问http://x86-64.org/documentation/abi.pdf,但该网站现已脱离互联网.
该文件是否有新的权威主页?
我试图了解地址计算指令的工作原理,尤其是leaq命令.然后当我看到leaq用于进行算术运算的例子时,我感到困惑.例如,以下C代码,
long m12(long x) {
return x*12;
}
Run Code Online (Sandbox Code Playgroud)
在组装中
leaq (%rdi, %rdi, 2), %rax
salq $2, $rax
Run Code Online (Sandbox Code Playgroud)
如果我的理解是正确的,那么leaq应该移动任何(%rdi, %rdi, 2)应该2*%rdi+%rdi评估的地址%rax.我感到困惑的是,因为值x存储%rdi在内,这只是内存地址,为什么%rdi乘以3然后左移这个内存地址 2等于x乘以12?是不是当我们%rdi用3时,我们跳到另一个没有值x的内存地址?
我正在研究低级位黑客,并想为每个黑客编写一个汇编程序。这是我检查数字是否偶数的方法:
is_even:
# check if an integer is even.
# This is the same as seeing if its a multiple of two, i.e., & 1<<n - 1
# rdi stores the number
xor %eax, %eax
test $0b1, %rdi
setz %al
ret
_start:
mov $5, %rdi
call is_even
Run Code Online (Sandbox Code Playgroud)
有什么方法可以改进上述内容或使其更具可读性?是否可以is_even使用 2 条指令而不是 3 条指令进行检查,因为第一条xor和第二条指令setz似乎可能会转换为一条(如果可能的话)。
assembly ×4
x86 ×4
c++ ×3
optimization ×3
abi ×2
c ×2
x86-64 ×2
boolean ×1
if-statement ×1
linux ×1
llvm ×1
llvm-codegen ×1
performance ×1