【发布时间】:2014-09-05 18:38:10
【问题描述】:
我正在转换一堆代码以使用 C++ 风格的强制转换(在 -Wold-style-cast 的帮助下)。我并不完全赞同它对原始变量的使用,但我通常对 C++ 风格的转换不熟悉。
在某些字节序转换代码中出现了一个问题。当前代码如下所示:
#define REINTERPRET_VARIABLE(VAR,TYPE) (*((TYPE*)(&VAR)))
//...
uint16_t reverse(uint16_t val) { /*stuff to reverse uint16_t*/ }
int16_t reverse( int16_t val) {
uint16_t temp = reverse(REINTERPRET_VARIABLE(val,uint16_t));
return REINTERPRET_VARIABLE(temp,int16_t);
}
现在,字节序不关心符号。因此,要反转int16_t,我们可以将其与uint16_t 完全一样地对待,以达到反转的目的。这建议这样的代码:
int16_t reverse( int16_t val) {
return reinterpret_cast<int16_t>(reverse(reinterpret_cast<uint16_t>(val)));
}
但是,如this 和特别是this 问题中所述,reinterpret_cast 需要一个引用或一个指针(除非它强制转换为自身)。这表明:
int16_t reverse( int16_t val) {
return reinterpret_cast<int16_t&>(reverse(reinterpret_cast<uint16_t&>(val)));
}
这不起作用,因为正如我的编译器告诉我的那样,外部强制转换需要一个左值。要解决此问题,您需要执行以下操作:
int16_t reverse( int16_t val) {
uint16_t temp = reverse(reinterpret_cast<uint16_t&>(val));
return reinterpret_cast<int16_t&>(temp);
}
这和原来的代码差别不大,确实临时变量的存在也是同理,但是给我提了四个问题:
- 为什么
reinterpret_cast甚至需要一个临时的?我可以理解一个愚蠢的编译器需要一个临时的来支持REINTERPRET_VARIABLE的指针肮脏,但reinterpret_cast应该只是重新解释位。这是与 RVO 冲突还是什么? - 要求该临时值是否会导致性能损失,或者编译器是否可以确定该临时值真的应该只是返回值?
- 第二个
reinterpret_cast看起来像是在返回一个引用。由于函数返回值不是参考,我很确定这没问题;返回值将是副本,而不是引用。但是,我仍然想知道强制转换到引用的真正含义是什么?在这种情况下是合适的,对吧? - 还有其他我应该注意的性能影响吗?我猜
reinterpret_cast会更快,因为编译器不需要弄清楚这些位应该被重新解释——我只是告诉他们应该?李>
【问题讨论】:
-
如果您的编译器套件还没有为您提供一些字节交换函数/宏,我会感到惊讶... GCC 提供了一个名为
byteswap.h的标头,其中包含 16/32/64-位字节交换实现。其他编译器可能会将它们放在不同的头文件中... -
确实,我遇到了同样的问题。我想知道你现在有什么想法吗?
-
@astroboyrx 查看新分配的答案。
-
如果您可以尝试完全避免演员阵容会更好。