相关疑难解决方法(0)

使用(float&)int工作类型punning,(float const&)int转换为(float)int而不是?

VS2019,发布,x86.

template <int i> float get() const {
    int f = _mm_extract_ps(fmm, i);
    return (float const&)f;
}
Run Code Online (Sandbox Code Playgroud)

使用return (float&)f;编译器时使用

extractps m32, ...
movss xmm0, m32
Run Code Online (Sandbox Code Playgroud)

.正确的结果

使用return (float const&)f;编译器时使用

extractps eax, ...
movd xmm0, eax
Run Code Online (Sandbox Code Playgroud)

.错误的结果

T&和T const&首先是T然后是const的主要思想.Const只是程序员的某种协议.你知道你可以解决它.但汇编代码中没有任何const,但是类型为float IS.我认为对于float和float const而言它必须是汇编中的浮点表示(cpu寄存器).我们可以使用中间int reg32,但最终解释必须是float.

而此时它看起来像回归,因为这之前工作正常.并且在这种情况下使用float也绝对是奇怪的,因为我们不应该考虑浮动const和安全性而是浮动的临时变量并且确实值得怀疑.

微软回答:

嗨Truthfinder,感谢自成一体的复制品.碰巧,这种行为实际上是正确的.正如我的同事@Xiang Fan [MSFT]在内部电子邮件中所述:

由[a c-style cast]执行的转换尝试以下序列:(4.1) - const_cast(7.6.1.11),(4.2) - static_cast(7.6.1.9),(4.3) - static_cast后跟const_cast ,(4.4) - reinterpret_cast(7.6.1.10)或(4.5) - reinterpret_cast后跟const_cast,

如果转换可以用上面列出的多种方式解释,则使用列表中首先出现的解释.

所以在你的情况下,(const float&)被转换为static_cast,其效果是"初始化表达式被隐式转换为类型为"cv1 T1"的prvalue.应用临时实现转换并将引用绑定到结果".

但在另一种情况下,(float&)被转换为reinterpret_cast,因为static_cast无效,这与reinterpret_cast(&operand)相同.

您正在观察的实际"错误"是一个强制转换:"将浮点型值"1.0"转换为等效的int-typed值"1"",而另一个强制转换说"将1.0的位表示形式转换为一个浮点数,然后将这些位解释为int".

出于这个原因,我们建议不要使用c风格的演员表.

谢谢!

MS论坛链接:https://developercommunity.visualstudio.com/content/problem/411552/extract-ps-intrinsics-bug.html

有任何想法吗?

PS我真正想要的是什么:

float val …
Run Code Online (Sandbox Code Playgroud)

c++ assembly sse intrinsics visual-c++

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

memmove有效类型的原位变更(类型 - 双关语)

在下面的问题中: 什么是将一个浮点数类型化为int的正确方法,反之亦然?,结论是从整数位构造双精度的方法,反之亦然memcpy.

那很好,pseudo_cast转换方法有:

template <typename T, typename U>
inline T pseudo_cast(const U &x)
{
    static_assert(sizeof(T) == sizeof(U));    
    T to;
    std::memcpy(&to, &x, sizeof(T));
    return to;
}
Run Code Online (Sandbox Code Playgroud)

我会像这样使用它:

int main(){
  static_assert(std::numeric_limits<double>::is_iec559);
  static_assert(sizeof(double)==sizeof(std::uint64_t));
  std::uint64_t someMem = 4614253070214989087ULL;
  std::cout << pseudo_cast<double>(someMem) << std::endl; // 3.14
}
Run Code Online (Sandbox Code Playgroud)

我只是阅读标准和cppreference的解释是,也应该可以用来就地memmove改变有效类型,如下所示:

template <typename T, typename U>
inline T& pseudo_cast_inplace(U& x)
{
    static_assert(sizeof(T) == sizeof(U));
    T* toP = reinterpret_cast<T*>(&x);
    std::memmove(toP, &x, sizeof(T));
    return *toP;
}

template <typename T, typename U> …
Run Code Online (Sandbox Code Playgroud)

c++ type-punning

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

C++ 联合成员访问和未定义行为

我目前正在从事一个项目,其中提供了以下结构。我的工作是 C++,但该项目同时使用 C 和 C++。C 和 C++ 都使用相同的结构定义。

typedef struct PacketHeader {
    //Byte 0
    uint8_t  bRes                           :4;
    uint8_t  bEmpty                         :1;
    uint8_t  bWait                          :1;
    uint8_t  bErr                           :1;
    uint8_t  bEnable                        :1;
    //Byte 1
    uint8_t  bInst                          :4;
    uint8_t  bCount                         :3;
    uint8_t  bRres                          :1;
    //Bytes 2, 3
    union {
        uint16_t wId;    /* Needed for Endian swapping */
        struct{
            uint16_t wMake                  :4;
            uint16_t wMod                   :12;
        };
    };
} PacketHeader;
Run Code Online (Sandbox Code Playgroud)

根据结构实例的使用方式,结构所需的字节序可以是大端或小端。由于结构的前两个字节都是单个字节,因此当字节序更改时不需要更改这些字节。字节 2 和 3 存储为单个uint16_t,是我们需要交换以实现所需字节顺序的唯一字节。为了实现字节序交换,我们一直在执行以下操作:

//Returns a constructed instance of PacketHeader with relevant fields …
Run Code Online (Sandbox Code Playgroud)

c++ undefined-behavior unions language-lawyer

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

优化小3d矢量结构的性能

我是C++的新手,有以下内容,让我们称之为问题.在我的计算机模拟中,我使用矢量工作了很多.我自己构建了一个表示向量的小结构,并希望学习如何进行操作(例如normalize()函数更有效.另外,使用C++有什么好处valarray吗?似乎有一些有用的方法预先实现.

我差点专门用 normalize()向量函数和加法/减法/乘法.由于我的所有向量只有三个元素,我对在项目中包含第三方库犹豫不决.

这是我的结构:

struct vector_t {
    int _i, _j, _k;
    vector_t(int i, int j, int k) {
        _i = i;
        _j = j;
        _k = k;
    }
    vector_t() {}
    inline int getI() { 
        return _i; 
    }
    inline int getJ() { 
        return _j; 
    }
    inline int getK() { 
        return _k; 
    }
    inline void setI(int val) { 
        _i = val; 
    }
    inline void setJ(int val) { 
        _j = val; 
    }
    inline void setK(int val) { 
        _k …
Run Code Online (Sandbox Code Playgroud)

c++ struct vector

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

按位转换uint32_t以在C/C++中浮动

我从网络接收缓冲区,该缓冲区被转换为32位字的数组.我有一个单词被我的界面文档定义为ieee float.我需要从缓冲区中提取这个单词.在不调用转换的情况下从一种类型转换为另一种类型很困难.这些位已经符合ieee浮点标准,我不想重新排列任何位.

我的第一次尝试是将地址转换uint32_t为a void*,然后将其转换void*为a float*,然后取消引用为float:

float ieee_float(uint32_t f)
{
    return *((float*)((void*)(&f)));
}
Run Code Online (Sandbox Code Playgroud)

错误:解除引用类型惩罚指针将破坏严格别名规则[-Werror = strict-aliasing]

我的第二次尝试是这样的:

float ieee_float(uint32_t f)
{
    union int_float{
        uint32_t i;
        float f;
    } tofloat;

    tofloat.i = f;
    return tofloat.f;
}
Run Code Online (Sandbox Code Playgroud)

然而,街上的一句话是,工会完全不安全.从最近没有编写的联合成员读取它是未定义的行为.

所以我尝试了更多的C++方法:

float ieee_float(uint32_t f)
{
  return *reinterpret_cast<float*>(&f);
}
Run Code Online (Sandbox Code Playgroud)

错误:解除引用类型惩罚指针将破坏严格别名规则[-Werror = strict-aliasing]

我的下一个想法是"搞砸它.为什么我要处理指针呢?" 并尝试过:

float ieee_float(uint32_t f)
{
  return reinterpret_cast<float>(f);
}
Run Code Online (Sandbox Code Playgroud)

错误:从'uint32_t {aka unsigned int}'类型无效转换为'float'类型

有没有办法在不触发警告/错误的情况下进行转换?我用g ++编译-Wall -Werror.我宁愿不接触编译器设置.

我标记了C,因为c解决方案是可以接受的.

c++

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

C++中安全高效的Punning类型

uint32_t Seed() {
    uint64_t seed = GetSomeReasonable64BitIntegerSeed();
    return *(uint32_t*)&seed ^ *((uint32_t*)&seed + 1);
}
Run Code Online (Sandbox Code Playgroud)

上面不是真正的代码,但这基本上是真正的代码所做的.我从g ++那里得到一个警告,它违反了严格的别名,谷歌搜索它,好吧我想解决它.我发现了这个问题,但它没有提供一个明确的解决方案,除了使用memcpy或依赖于未定义但实际上没有问题的行为,即访问联合的未设置成员.

我能想到的当前选择是,

  1. 使用memcpy.
  2. 使用a union并将此部分编译为C,其中语言标准允许通过联合进行类型惩罚.

c++ casting type-punning

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

设置一个双字节数组

什么是在字节数组中分配一个double到8个字节的快速方法?

我有一个大约4k字节的字节数组,我试图从中取出8个字节并将其复制到一个double中.我试图避免memmove和memcpy出于速度原因,因为分配变量要快得多.我在嵌入式世界工作,任何其他快速实现都受到赞赏.

void foo(double *pdest)
{
   // Try 1: I am using 1 element in the array, it won't work
   *pdest = (double)p->stk[stkpos];

   // Try 2: I am attempting to loose the single element element
   *pdest = (double)((double*)&p->stk[stkpos]);
}
Run Code Online (Sandbox Code Playgroud)

这两种解决方案都没有对我有用,我不确定如何实现这一目标.

c embedded double variable-assignment

-3
推荐指数
2
解决办法
97
查看次数