小编Tre*_*ntP的帖子

基于范围的 for 数组 ODR 循环是否使用该数组?

当使用基于范围的 for 循环来迭代数组而不将引用绑定到每个元素时,这是否构成数组的 ODR 使用?

例子:

struct foo {
    static constexpr int xs[] = { 1, 2, 3 };
};

int test(void) {
    int sum = 0;
    for (int x : foo::xs) // x is not a reference!
        sum += x;
    return sum;
}

// Definition, if needed
///constexpr foo::xs;
Run Code Online (Sandbox Code Playgroud)

的定义有foo::xs必要吗?

虽然此代码及其变体似乎运行良好,但这并不意味着该定义永远不需要。缺乏 ODR 使用变量的定义很少会产生诊断,因为该变量可以在另一个翻译单元中定义。链接器错误是常见的结果,但如果编译器能够优化每次使用,则很可能不会出现错误,这就是上述代码所发生的情况。编译器有效地简化test()return 6;.

将引用绑定到元素将是 ODR 使用,但这还没有完成。

我的印象是,在 C++14 或更高版本中,为数组添加下标不是 ODR 使用。但基于的范围并不完全是下标。

在 C++17 中,我相信这个示例避免了这个问题,因为 constexpr 类数据成员是隐式内联的。因此,类中的声明也用于定义xs,并且不需要额外的命名空间范围定义来满足 ODR。

同一问题的一些附加版本:

如果我们使用std::array …

c++ one-definition-rule c++14

6
推荐指数
1
解决办法
123
查看次数

一种从本地 sysroot 和远程 gdbserver 加载 GDB 库的方法

在使用 gdbserver 进行远程调试时,我想让 gdb 从本地 sysroot 加载正在调试的程序的一些共享库,但也允许从 gdbserver 下载功能加载其他不在 sysroot 中的功能。

gdb 似乎只能使用一种方法来查找库、本地文件或远程下载,而不能同时使用这两种方法。

例如,如果我将 sysroot 设置target:/为使用远程文件,则所有内容都将被下载:

(gdb) set sysroot target:/
(gdb) run
Starting program:  
Reading /root/a.out from remote target...
warning: File transfers from remote targets can be slow. Use "set sysroot" to access files locally instead.
Reading /root/a.out from remote target...
Reading symbols from target:/root/a.out...
Reading /lib/ld-linux-armhf.so.3 from remote target...
Run Code Online (Sandbox Code Playgroud)

不幸的是,远程系统上的系统库没有调试符号。它是一个闪存空间有限的嵌入式系统。调试符号会大大增加文件系统的总大小,而且根本不适合。

但是,我有一个所有系统库的本地 sysroot 树,这确实包括调试符号。但是如果我将 sysroot 设置为这棵树,gdb 将不再考虑远程下载。

(gdb) set sysroot /bsp/sysroot
(gdb) run
Starting program:  
Reading symbols from …
Run Code Online (Sandbox Code Playgroud)

debugging gdb gdbserver

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

用于通用 SIMD(SSE、AVX、NEON)测试零匹配的高效 C 向量。(求FP最大绝对值和索引)

我想看看是否可以编写一些可以高效编译的通用 SIMD 代码。主要用于 SSE、AVX 和 NEON。该问题的简化版本是:找到浮点数数组的最大绝对值并返回该值和索引。导致问题的是最后一部分,即最大值的索引。似乎没有一个很好的方法来编写具有分支的代码。

请参阅最后的更新,以获取使用一些建议答案的完成代码。

这是一个示例实现(godbolt上更完整的版本):

#define VLEN 8
typedef float vNs __attribute__((vector_size(VLEN*sizeof(float))));
typedef int vNb __attribute__((vector_size(VLEN*sizeof(int))));
#define SWAP128 4,5,6,7, 0,1,2,3
#define SWAP64 2,3, 0,1,  6,7, 4,5
#define SWAP32 1, 0,  3, 2,  5, 4,  7, 6

static bool any(vNb x) {
    x = x | __builtin_shufflevector(x,x, SWAP128);
    x = x | __builtin_shufflevector(x,x, SWAP64);
    x = x | __builtin_shufflevector(x,x, SWAP32);
    return x[0];
}

float maxabs(float* __attribute__((aligned(32))) data, unsigned n, unsigned *index) {
    vNs max = {0,0,0,0,0,0,0,0}; …
Run Code Online (Sandbox Code Playgroud)

c gcc sse simd neon

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

安全地将整数与强类型枚举进行比较

当积分值可能不在枚举值范围内时,如何安全地将未知类型的积分值与强类型枚举进行比较?

将整数值与枚举进行比较的最明显方法是将整数值转换a为枚举类型E,并与枚举值进行比较b,如下所示:

template <typename I, typename E>
bool compare(I a, E b) { return static_cast<E>(a) == b; }
Run Code Online (Sandbox Code Playgroud)

但是,如果a不在枚举值的范围内,则会导致未指定的行为,根据[expr.static.cast]/10:

可以将整数或枚举类型的值显式转换为枚举类型.如果原始值在枚举值(7.2)的范围内,则该值不变.否则,结果值未指定(可能不在该范围内).

这可以在导致的失败中看到(compare如上所述):

enum E : uint8_t { A = 0 };
compare(256, E::A); // returns true, 256 == E::A, but E::A = 0
Run Code Online (Sandbox Code Playgroud)

可以将枚举转换为整数类型,但如果整数类型不能表示所有枚举值,则可能导致错误的结果:

enum E : int { A = 256 };
template <typename I, typename E>
bool compare(I a, E b) { return a == static_cast<I>(b); } …
Run Code Online (Sandbox Code Playgroud)

c++ c++11

4
推荐指数
1
解决办法
1329
查看次数

标签 统计

c++ ×2

c ×1

c++11 ×1

c++14 ×1

debugging ×1

gcc ×1

gdb ×1

gdbserver ×1

neon ×1

one-definition-rule ×1

simd ×1

sse ×1