相关疑难解决方法(0)

什么是严格别名规则?

当询问C中常见的未定义行为时,灵魂比我提到的严格别名规则更加开明.
他们在说什么?

c strict-aliasing undefined-behavior type-punning

778
推荐指数
10
解决办法
19万
查看次数

为什么优化会破坏此功能?

我们最近在大学里开了一个关于多种语言编程特色的讲座.

讲师写下了以下功能:

inline u64 Swap_64(u64 x)
{
    u64 tmp;
    (*(u32*)&tmp)       = Swap_32(*(((u32*)&x)+1));
    (*(((u32*)&tmp)+1)) = Swap_32(*(u32*) &x);

    return tmp;
}
Run Code Online (Sandbox Code Playgroud)

虽然我完全理解这在可读性方面也是非常差的风格,但他的主要观点是这部分代码在生产代码中运行良好,直到它们实现了高优化级别.然后,代码将什么都不做.

他说,变量的所有赋值tmp都将由编译器优化.但为什么会这样呢?

我知道有些情况下变量需要声明为volatile,这样编译器就不会触及它们,即使他认为它们永远不会被读或写,但我不知道为什么会发生这种情况.

c c++ optimization endianness strict-aliasing

49
推荐指数
3
解决办法
4343
查看次数

最有效的符合标准的方法,将int重新解释为float

假设我有floatIEEE 754 binary32的保证.给定一个与存储的有效浮点相对应的位模式std::uint32_t,如何float以最有效的标准兼容方式将其重新解释为?

float reinterpret_as_float(std::uint32_t ui) {
   return /* apply sorcery to ui */;
}
Run Code Online (Sandbox Code Playgroud)

我有几种方法,我知道/怀疑/假设有一些问题:

  1. 通过reinterpret_cast,

    float reinterpret_as_float(std::uint32_t ui) {
        return reinterpret_cast<float&>(ui);
    }
    
    Run Code Online (Sandbox Code Playgroud)

    或者等价的

    float reinterpret_as_float(std::uint32_t ui) {
        return *reinterpret_cast<float*>(&ui);
    }
    
    Run Code Online (Sandbox Code Playgroud)

    哪个遭受别名问题.

  2. 通过union,

    float reinterpret_as_float(std::uint32_t ui) {
        union {
            std::uint32_t ui;
            float f;
        } u = {ui};
        return u.f;
    }
    
    Run Code Online (Sandbox Code Playgroud)

    这实际上并不合法,因为它只允许从最近写的成员读取.然而,似乎有些编译器(gcc)允许这样做.

  3. 通过std::memcpy,

    float reinterpret_as_float(std::uint32_t ui) {
        float f;
        std::memcpy(&f, &ui, 4);
        return f;
    }
    
    Run Code Online (Sandbox Code Playgroud)

    哪种AFAIK是合法的,但复制单个单词的函数调用似乎很浪费,尽管它可能会被优化掉.

  4. 通过reinterpret_cast …

c++ standards-compliance type-conversion language-lawyer c++11

31
推荐指数
1
解决办法
4324
查看次数

什么是将一个浮点数类型化为int的正确方法,反之亦然?

下面的代码通过一些位攻击执行快速反平方根操作.该算法可能是由Silicon Graphics在1990年代早期开发的,它也出现在Quake 3中. 更多信息

但是我从GCC C++编译器收到以下警告:解除引用类型惩罚指针将破坏严格别名规则

我应该使用static_cast,reinterpret_cast还是dynamic_cast在这种情况下使用?

float InverseSquareRoot(float x)
{
    float xhalf = 0.5f*x;
    int32_t i = *(int32_t*)&x;
    i = 0x5f3759df - (i>>1);
    x = *(float*)&i;
    x = x*(1.5f - xhalf*x*x);
    return x;
}
Run Code Online (Sandbox Code Playgroud)

c++ strict-aliasing gcc-warning undefined-behavior type-punning

24
推荐指数
4
解决办法
6830
查看次数

C++严格别名不可知的演员

我已经在Stack Overflow中阅读了很多关于严格别名的QA,但它们都很常见,而且讨论总是倾向于引用C++标准的深层细节,这些细节几乎总是很难理解.特别是在标准时,不要直接说话,而是用泥泞不清楚的方式描述.所以,我的问题可能是这里有大量质量保证的重复,但是,请回答一个具体的问题:

这是做"nonalias_cast"的正确方法吗?:

template<class OUT, class IN>
inline auto nonalias_cast(IN *data) {
    char *tmp = reinterpret_cast<char *>(data);
    return reinterpret_cast<OUT>(tmp);
}

float f = 3.14;
unsigned *u = nonalias_cast<unsigned *>(&f);
*u = 0x3f800000;
// now f should be equal 1.0
Run Code Online (Sandbox Code Playgroud)

我猜答案是否定的.但是有什么好的解决方法吗?当然,除了禁用严格别名标志.联盟也不是一个方便的选择,除非有一种方法在nonalias_cast函数体内部适合联合黑客.memcpy这里也不是一个选项 - 数据更改应该是同步的.

一个不可能的梦想或一个难以捉摸的现实?

UPD:

好的,既然我们得到了一个否定答案"是否可能?" 问题,我想问你一个困扰我的额外问题:

将如何解决这个任务?我的意思是有很多实际的任务,更多的是要求"玩一点点"的方法.例如,假设您必须像这样编写IEEE-754浮点转换器.我更关注问题的实际方面:如何有一个解决方法来实现目标?至少在"#$ $的痛苦"方式.

c++ strict-aliasing

4
推荐指数
2
解决办法
311
查看次数