小编Oli*_*ock的帖子

当传递 -fsanitize=undefined 时,来自 gcc-trunk 的 -Wconversion 诊断

short int这是关于在“常规算术转换”期间提升 s时的正确诊断。在操作期间,/可以合理地发出诊断信息,但在操作期间/=不应发出任何诊断信息。

gcc-trunk 和 clang-trunk 的行为似乎没问题(都不发出下面第一种或第二种情况的诊断信息)...直到...

我们添加了完全不相关的-fsanitize=undefined...之后,完全奇怪的是:

gcc-trunk 会针对这两种情况发出诊断信息。至少对于第二种情况确实不应该。

这是 gcc 中的错误吗?

神箭链接

Godbolt 与 -O3 链接 - 相同的结果

int main() {
    short sum   = 50;
    short count = 10;

    // sum and count get promoted to int for the "usual arithmetic conversions"
    // then the assignment could result in a reasonable -Wconversion diagnostic for reduction back
    // to short
    // However clang-trunk and gcc-trunk choose NOT TO issue a diagnostic …
Run Code Online (Sandbox Code Playgroud)

c++ gcc language-lawyer

7
推荐指数
1
解决办法
168
查看次数

msvc std::lower_bound 需要 const 运算符*

我得到了

Error   C2678   binary '*': no operator found which takes a left-hand operand of type 'const _InIt' (or there is no acceptable conversion)
Run Code Online (Sandbox Code Playgroud)

它是由 MSVC (2022, V17.1) 标头中的代码抛出的<algorithm>

Error   C2678   binary '*': no operator found which takes a left-hand operand of type 'const _InIt' (or there is no acceptable conversion)
Run Code Online (Sandbox Code Playgroud)

const由于上面一行的原因,第二行抛出了错误。

我传入的迭代器是“平面文件”上的自定义 LegacyRandomAccessIterator,它operator*看起来像这样:

template <class _FwdIt, class _Ty, class _Pr>
_NODISCARD _CONSTEXPR20 _FwdIt lower_bound(_FwdIt _First, const _FwdIt _Last, const _Ty& _Val, _Pr _Pred) {

... …
Run Code Online (Sandbox Code Playgroud)

c++ const-correctness

7
推荐指数
1
解决办法
221
查看次数

使用 std::array&amp; 分配 C 样式数组的一个子部分而不违反“严格别名”并因此调用 UB?

我可以使用 astd::array<int, N>来为 a 的部分别名int[]而不调用 UB 吗?

https://en.cppreference.com/w/cpp/container/array “此容器是一个聚合类型,其语义与将 C 样式数组 T[N] 作为其唯一非静态数据成员的结构体具有相同的语义。 ”

动机:copy下面的函数不受我的控制,需要通过引用进行单个分配。只有 a struct { int[N]; }like astd::array<int, N>才能进行那种“多对象赋值”?

这是UB吗?

还有别的办法吗?

#include <iostream>
#include <array>

template <std::size_t N>
void print(int (&arr)[N], std::size_t number_rows, std::size_t number_cols) {
    assert(number_rows * number_cols == N);
    for (std::size_t r = 0; r != number_rows; ++r) {
        for (std::size_t c = 0; c != number_cols; ++c) {
            std::cout << arr[r * number_cols + c] …
Run Code Online (Sandbox Code Playgroud)

c++ strict-aliasing undefined-behavior stdarray

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

提高通用交换的性能

语境

在 C 中实现处理一系列类型的泛型函数时,void*经常使用。该libc函数qsort()是一个经典的例子。在内部qsort()和许多其他算法中都需要一个swap()函数。

通用交换的一个简单但典型的实现如下所示:

void swap(void* x, void* y, size_t size) {
    char t[size];
    memcpy(t, x, size);
    memcpy(x, y, size);
    memcpy(y, t, size);
}
Run Code Online (Sandbox Code Playgroud)

对于较大的类型,可以使用逐字节交换,否则malloc会很慢,但这里的重点是当这个泛型swap()用于小类型时会发生什么。

更好的通用交换?

事实证明,如果我们匹配一些常见的类型大小(x86_64 上的 4 和 8 字节的 int 和 long),还包括浮点、双精度、指针等,我们可以获得令人惊讶的性能提升:

void swap(void* x, void* y, size_t size) {
  if (size == sizeof(int)) {
    int t      = *((int*)x);
    *((int*)x) = *((int*)y);
    *((int*)y) = t;
  } else if (size == sizeof(long)) { …
Run Code Online (Sandbox Code Playgroud)

c generics swap memcpy

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

如何处理通用代码中可能混合的有符号和无符号算术?

混合有符号和无符号算术的典型示例似乎是:

\n
    unsigned int u = 10;\n    int          a = -42;\n    auto tmp1 = u - a;\n    std::cout << tmp1 << std::endl;\n    int tmp2 = tmp1;\n    std::cout << tmp2 << std::endl;\n
Run Code Online (Sandbox Code Playgroud)\n

(请注意,我使用的是auto tmp1这样我可以显示中间结果并检查类型。当然,在实际代码中,这都是一行)

\n

如果你启用足够多的警告(-Wconversion在 clang-13 上,另外,-Wsign-conversion在 gcc-11 上),编译器会很好地抱怨:

\n
main.cpp:148:21: warning: conversion to \xe2\x80\x98unsigned int\xe2\x80\x99 from \xe2\x80\x98int\xe2\x80\x99 may change the sign of the result [-Wsign-conversion]\n  148 |     auto tmp1 = u - a;\n      |                     ^\nmain.cpp:150:16: warning: conversion to \xe2\x80\x98int\xe2\x80\x99 from \xe2\x80\x98unsigned int\xe2\x80\x99 …
Run Code Online (Sandbox Code Playgroud)

c++ unsigned signed

5
推荐指数
0
解决办法
380
查看次数

使用 struct 分块处理数组,然后将其转换为平面数组 - 如何避免 UB(严格别名)?

外部 API 需要一个指向值数组(此处为 int 作为简单示例)的指针加上一个大小。

以 4 为一组处理元素在逻辑上更清晰。

因此,通过“4 组”结构处理元素,然后使用指针转换将这些结构的数组传递到外部 API。请参阅下面的代码。

蜘蛛感知说:=> 可能的 UB 中存在“严格混叠违规” reinterpret_cast

  1. 以下内容static_asserts是否足以确保:a) 这在实践中有效 b) 这实际上符合标准而不是 UB?

  2. 否则,我需要做什么,才能使其“不是UB”。工会?请问具体怎么样?

  3. 或者,是否有一种不同的、更好的方法?


#include <cstddef>

void f(int*, std::size_t) {
    // external implementation
    // process array
}

int main() {

    static constexpr std::size_t group_size    = 4;
    static constexpr std::size_t number_groups = 10;
    static constexpr std::size_t total_number  = group_size * number_groups;

    static_assert(total_number % group_size == 0);

    int vals[total_number]{};

    struct quad {
        int val[group_size]{};
    };

    quad vals2[number_groups]{};
    // deal with …
Run Code Online (Sandbox Code Playgroud)

c++ strict-aliasing undefined-behavior language-lawyer

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

使用单个 int 的初始值设定项列表进行 int 与 std::vector&lt;int&gt; 的重载解析

为什么 C++ 选择原始类型重载匹配而不是“更好”的匹配初始值设定项列表?


#include <vector>

void foo([[maybe_unused]] int i) {}

void foo([[maybe_unused]] const std::vector<int>& v) {}

int main() {
    foo(0);
    foo({1,2,3});
    foo({0}); // calls foo(int) and issues a warning,
              // rather than what seems like the "better"
              // match foo(vector).. why? 
}
Run Code Online (Sandbox Code Playgroud)
<source>:10:9: warning: braces around scalar initializer [-Wbraced-scalar-init]
    foo({0}); // calls foo(int) and issues a warning,
        ^~~
Run Code Online (Sandbox Code Playgroud)

也许是“令人惊讶”的结果,因为编译器选择了随后发出诊断的选项?

使用 Clang 14

https://godbolt.org/z/1dscc5hM4

c++ overloading initializer-list language-lawyer overload-resolution

3
推荐指数
1
解决办法
156
查看次数