我在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浮点转换器。我更关注问题的实际方面:如何有一个解决方法来实现目标?至少在“#$ $的痛苦”方式。
答案 0 :(得分:5)
这是一种正确的方式来做一个&#34; nonalias_cast&#34;?
没有
但是有什么好的解决方法吗?
再次,不。
两者的原因很简单,&f
不是unsigned int
类型的某个对象的地址,并且指针上的任何投射量都不会改变它。
答案 1 :(得分:5)
正如其他答案已正确指出:这是不可能的,因为您不允许通过float
指针访问unsigned
对象,并且没有会删除该规则的强制转换。< / p>
那么你如何解决这个问题呢?不要通过unsigned
指针访问对象!使用float*
或char*
传递对象,因为这些是严格别名下允许的唯一指针类型。然后,当您确实需要访问unsigned
语义下的对象时,您需要memcpy
从float*
到本地unsigned
{和memcpy
返回一次完成)。您的编译器will be smart enough to generate efficient code for this。
请注意,这意味着您的界面上只有float*
而不是unsigned*
。这正是使这项工作的原因:类型系统始终了解正确的数据类型。如果你试图通过类型系统将float
作为unsigned*
走私,事情就会开始崩溃,你首先希望这是一种愚蠢的想法。
答案 2 :(得分:4)
不,您的nonalias_cast
不起作用,无法正常工作。
类型别名规则不是(直接)关于转换指针的。实际上,您的所有转化都没有未定义的行为。规则是通过另一种类型的指针访问某种类型的对象。
无论您如何转换指针,指向的对象仍然是float
对象,通过unsigned
指针访问它会违反类型别名规则。
一个不可能的梦想还是一个难以捉摸的现实?
在标准C ++中,这是不可能的。