这个严格的别名示例是否正确? [英] Is this strict aliasing example correct?

查看:124
本文介绍了这个严格的别名示例是否正确?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在过去一周左右,我一直在阅读严格的别名规则,并遇到了这篇文章:了解C / C ++ Strict Aliasing

I've been reading up on the strict aliasing rules over the last week or so and ran into this article: Understanding C/C++ Strict Aliasing.

本文通过几种方法交换了32位整数的两半,给出了两个好的例子,严格混叠规则。

The article goes through several ways two swap the halves of a 32-bit integer, giving both good examples and ones that violate the strict aliasing rule. I'm having trouble understanding one of the examples, though.

这段代码被描述为破碎。

This code is described as broken.

uint32_t
swaphalves(uint32_t a)
{
    a = (a >> 16) | (a << 16);
    return a;
}

原因是:


这个版本看起来很合理,但你不知道是否右侧和左侧的
|将获得 a 的原始版本,或者其中一个将获得
的结果。这里没有序列点,所以我们不知道任何关于
操作的顺序,你可能会得到不同的结果从同一个编译器使用不同的
优化水平。

This version looks reasonable, but you don't know if the right and left sides of the | will each get the original version of a or if one of them will get the result of the other. There's no sequence point here, so we don't know anything about the order of operations here, and you may get different results from the same compiler using different levels of optimization.

我不同意。这段代码对我看起来不错。在 a =(a>> 16 |(a<< 16); a c $ c>行,我希望 a 的两个读取发生在写入之前。此外,没有指针或引用和不兼容的类型。

I disagree. This code looks fine to me. There is only one write to a in the a = (a >> 16 | (a << 16); line, and I expect that both reads of a take place before that write. Further, there are no pointers or references and no incompatible types.

我在这段代码中缺少严格的别名冲突,或者文章不正确?

Am I missing a strict aliasing violation in this code, or is the article incorrect?

推荐答案

在这段代码中没有指针和引用,所以严格的别名规则甚至不输入图片。作者确实调用了序列点而不是严格的别名来证明它的undefined。但是,这种推理似乎是错误的,代码段具有完美定义的语义。如 Prasoon Saurav更详细地解释

There are no pointers and references anywhere in this code, so strict aliasing rules don't even enter the picture. And indeed the author invokes sequence points rather than strict aliasing to justify the assertion that it's undefined. However, it seems this reasoning is wrong and the code snippet has perfectly defined semantics. As Prasoon Saurav explains in more detail:


(§1.9/ 15)操作符的操作数的值计算在操作符结果的值计算之前

因此,对于 = c> a 和(a> 16)| (a<< 16)在分配之前排序。这两个都不成问题:虽然它的部分都不相对于彼此,不写 a 仍然需要排序。

So regarding the = operator, the evaluation of a and (a >> 16) | (a << 16) are sequenced before the assignment. Neither of those is problematic: Although its parts are all unsequenced relative to each other, no write to a remains that would need to be sequenced.

(技术上,这提出了一个问题,如何赋值的副作用排序wrt它的值计算,但我找不到任何东西在这可能是在标准的某个地方,但我没有a 强烈地怀疑其在下一段中的原因之后的值计算顺序。)

(Technically this raises the question of how the side effect of the assignment is sequenced w.r.t. its value computation, but I couldn't find anything on this. Presumably it's somewhere in the standard but I don't have a copy handy. I strongly suspect it's sequenced after the value computation for the reasons in the next paragraph.)

您也可以应用常识:写入 a 需要评估(a>> 16)| (a<<< 16)首先写入正确的值,因此它不会发生在评估的中间。文章的另一个问题是,即使

You could also apply common sense: The write to a needs to evaluate (a >> 16) | (a << 16) first to write the right value and hence it can't happen in the middle of that evaluation. Another issue with the article is that even if

uint32_t
swaphalves(uint32_t a)
{
    a = (a >> 16) | (a << 16);
    return a;
}

由于序列点而具有未定义的行为,

had undefined behavior due to sequence points,

uint32_t
swaphalves(uint32_t a)
{
    return (a >> 16) | (a << 16);
}

不会(没有要排序的写入)更复杂的版本(工会,memcpy)占据了文章的大部分其余部分是无意义的。

wouldn't (there are no writes to be sequenced) and hence the far more complicated versions (unions, memcpy) that take up most of the rest of the article are pointless.

这篇关于这个严格的别名示例是否正确?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆