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

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

问题描述

我已经在过去一周左右严格别名规则读了,跑进这篇文章:了解Ç / C ++严格别名

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.

是这样描述code作为打破。

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.

我不同意。这code看起来好像没什么问题。世界上只有一个写 A A =(A&GT;&GT; 16 |(A&LT;&LT; 16); 行,我希望 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.

我缺少一个严格别名违反本条code,或者是文章不正确的?

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

推荐答案

有没有指针或引用这个code的任何地方,所以严格别名规则,甚至不进入画面。事实上笔者调用的序列点的,而不是严格别名证明的说法,它是不确定的。然而,似乎这种推理是错误的,code段已完全被定义语义。由于 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)的操作的操作数的值计算是操作者的结果的值计算之前测序

(§1.9/15) The value computations of the operands of an operator are sequenced before the value computation of the result of the operator.

所以有关 = 运营商, A (A&GT的评价; &GT; 16)| (A&LT;&LT; 16)被赋值之前测序。这些都不是问题。虽然它的部分都是相互unsequenced,以 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其值计算的问题,但在这我无法找到任何东西。presumably它在标准的地方,但我没有复制得心应手。我的强烈的怀疑这是为下一段的原因值计算后测序。)

(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&GT;&GT; 16)| (A&LT;&LT; 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天全站免登陆