Nik*_*kin 4 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
Run Code Online (Sandbox Code Playgroud)
我猜答案是否定的.但是有什么好的解决方法吗?当然,除了禁用严格别名标志.联盟也不是一个方便的选择,除非有一种方法在nonalias_cast函数体内部适合联合黑客.memcpy这里也不是一个选项 - 数据更改应该是同步的.
一个不可能的梦想或一个难以捉摸的现实?
UPD:
好的,既然我们得到了一个否定答案"是否可能?" 问题,我想问你一个困扰我的额外问题:
将如何您解决这个任务?我的意思是有很多实际的任务,更多的是要求"玩一点点"的方法.例如,假设您必须像这样编写IEEE-754浮点转换器.我更关注问题的实际方面:如何有一个解决方法来实现目标?至少在"#$ $的痛苦"方式.
这是做"nonalias_cast"的正确方法吗?
没有.
但是有什么好的解决方法吗?
再一次,没有.
两者的原因很简单,那&f不是某个类型对象的地址unsigned int,并且指针上的任何投射都不会改变它.
正如其他答案已正确指出:这是不可能的,因为您不允许float通过unsigned指针访问对象,并且没有将删除该规则的强制转换.
那么你如何解决这个问题呢?不要通过unsigned指针访问对象!使用float*或char*传递对象,因为这些是严格别名下允许的唯一指针类型.然后当你真的需要在unsigned语义下访问对象时,你会memcpy从float*一个本地进行访问unsigned(memcpy一旦你完成就回来).您的编译器将足够智能,可以为此生成有效的代码.
请注意,这意味着您将float*在界面上的任何地方而不是unsigned*.这正是使这项工作的原因:类型系统始终了解正确的数据类型.如果你试图float通过类型系统偷偷摸摸的东西,事情才会开始崩溃unsigned*,你可能会认为这首先是一种愚蠢的想法.