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

时间:2017-10-09 10:30:58

标签: c++ strict-aliasing

我在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

我猜答案是没有。但是有什么好的解决方法吗?当然,除了禁用严格别名标志。 Union也不是一个方便的选项,除非有一种方法可以在nonalias_cast函数体内适合联合hack。 <{1}}也不是一个选项 - 数据更改应该同步。

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

UPD:

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

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

3 个答案:

答案 0 :(得分:5)

  

这是一种正确的方式来做一个&#34; nonalias_cast&#34;?

没有

  

但是有什么好的解决方法吗?

再次,不。

两者的原因很简单,&f不是unsigned int类型的某个对象的地址,并且指针上的任何投射量都不会改变它。

答案 1 :(得分:5)

正如其他答案已正确指出:这是不可能的,因为您不允许通过float指针访问unsigned对象,并且没有会删除该规则的强制转换。< / p>

那么你如何解决这个问题呢?不要通过unsigned指针访问对象!使用float*char*传递对象,因为这些是严格别名下允许的唯一指针类型。然后,当您确实需要访问unsigned语义下的对象时,您需要memcpyfloat*到本地unsigned {和memcpy返回一次完成)。您的编译器will be smart enough to generate efficient code for this

请注意,这意味着您的界面上只有float*而不是unsigned*。这正是使这项工作的原因:类型系统始终了解正确的数据类型。如果你试图通过类型系统将float作为unsigned*走私,事情就会开始崩溃,你首先希望这是一种愚蠢的想法。

答案 2 :(得分:4)

不,您的nonalias_cast不起作用,无法正常工作。

类型别名规则不是(直接)关于转换指针的。实际上,您的所有转化都没有未定义的行为。规则是通过另一种类型的指针访问某种类型的对象。

无论您如何转换指针,指向的对象仍然是float对象,通过unsigned指针访问它会违反类型别名规则。

  

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

在标准C ++中,这是不可能的。