小编l4m*_*4m2的帖子

在相同的表达式未定义行为中调用具有局部副作用的函数两次?

int f() {
    static int i=0;
    return ++i;
}
int g() {
    return f() + f();
}
Run Code Online (Sandbox Code Playgroud)

是否g()返回3或者是结果undefined

c undefined-behavior

24
推荐指数
3
解决办法
1530
查看次数

如何阻止 Clang 通过模板过度扩展嵌套循环?

考虑这段代码:

#include <iostream>
typedef long xint;
template<int N>
struct foz {
    template<int i=0>
    static void foo(xint t) {
        for (int j=0; j<10; ++j) {
            foo<i+1> (t+j);
        }
    }
    template<>
    static void foo<N>(xint t) {
        std::cout << t;
    }

};

int main() {
    foz<8>::foo<0>(0);
}
Run Code Online (Sandbox Code Playgroud)

在编译时clang++ -O0,它会在几秒钟内编译然后运行 ​​4 秒。

然而,使用clang++ -O2,编译需要很长的时间和大量的内存。在Compiler Explorer上可以看到,更改8为较小的值后,它完全展开了循环。

我并不是让它完全没有优化,而是让它不递归,就像嵌套循环应该表现的那样。有什么我应该做的吗?

c++ clang compiler-optimization template-meta-programming loop-unrolling

21
推荐指数
1
解决办法
1320
查看次数

虽然(i--)通过gcc和clang进行优化:为什么他们不使用sub/jnc?

有些人在需要没有计数器或计数器的循环时编写这样的代码n-1, ..., 0:

while (i--) { ... }
Run Code Online (Sandbox Code Playgroud)

一个具体的例子:

volatile int sink;
void countdown_i_used() {
    unsigned i = 1000;
    while (i--) {
         sink = i;  // if i is unused, gcc optimizes it away and uses dec/jnz
    }
}
Run Code Online (Sandbox Code Playgroud)

在GCC 8.2(在Godbolt编译器资源管理器上),它被编译成

# gcc8.2 -O3 -march=haswell
.L2:
    mov     DWORD PTR sink[rip], eax
    dec     eax                      # with tune=generic,  sub eax, 1
    cmp     eax, -1
    jne     .L2
Run Code Online (Sandbox Code Playgroud)

在clang(https://godbolt.org/z/YxYZ95)上,如果不使用计数器,它会变成

if(i) do {...} while(--i);
Run Code Online (Sandbox Code Playgroud)

但如果使用,就像GCC一样

add esi, -1
cmp …
Run Code Online (Sandbox Code Playgroud)

c performance x86 assembly gcc

9
推荐指数
1
解决办法
154
查看次数

我什么时候应该在 sqrtl 上使用 hypot?

它已经在这里讨论的是hypot比慢sqrt,因为它处理的情况下,当两个输入是巨大的或微小的,这样sqrt会错误地返回INF或0。

但是,根据一些测试hypot甚至比先转换为更高的精度然后再进行琐碎计算再转换回来还要慢。

那么,在什么情况下我应该使用hypot?只有当没有更大的浮点类型和溢出是一个问题?

编辑:sqrtlhypot在 input 上有所不同a=1,b=1.8e-8,但sqrtl返回更准确的结果:

hypot 1.0
sqrtl 1.000000000000000222044604925031
exact 1.000000000000000161999999999999986878000000000002125764000...
1+eps 1.0000000000000002220446049250313080847263336181640625
Run Code Online (Sandbox Code Playgroud)

确切线,其中的EPS被加入到结果示这里

c math performance

6
推荐指数
2
解决办法
219
查看次数

为什么C ++中的lambda包含所有引用?

使用g++.exe -m64 -std=c++17和任何优化级别进行编译,然后运行:

#include <iostream>

int main() {
    const auto L1 = [&](){};
    std::cout << sizeof(L1) << std::endl;
    const auto L2 = [&](){L1;};
    std::cout << sizeof(L2) << std::endl;
    const auto L3 = [&](){L1, L2;};
    std::cout << sizeof(L3) << std::endl;
    const auto L4 = [&](){L1, L2, L3;};
    std::cout << sizeof(L4) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

输出为1,8,16,24,这意味着L2包含1个引用,L3包含2个引用,L4包含3个引用。

但是,给定相同的功能“ [&](){L1, L2;}in main()”,的值&L1 - &L2应固定,并L1L2x 的指针一起使用,在x86中直接[rbx+const]假定为rbx=&L2。为什么GCC仍然选择在lambda中包含所有引用?

c++ optimization x86 lambda g++

5
推荐指数
1
解决办法
161
查看次数

为什么发布版本中的断言(0)不是未定义的行为?

.assert(x)应该表示x为真,因此编译器应该有权使用此信息进行优化.

例如,

char const* week(int n) {
    assert (n>=0 && n<7);
    switch (n) {
        case 0: return "Sunday";
        ...
        case 6: return "Saturday";
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

可以优化成

char const* week(int n) {
    char const* const* const x = {"Sunday", ..., "Saturday"};
    return x[n];
}
Run Code Online (Sandbox Code Playgroud)

并删除CMP n,7

c undefined-behavior

0
推荐指数
1
解决办法
201
查看次数