那么将一个单词分成两个字节的最快方法是什么?
short s = 0x3210;
char c1 = s >> 8;
char c2 = s & 0x00ff;
相对
short s = 0x3210;
char c1 = s >> 8;
char c2 = (s << 8) >> 8;
编辑
怎么样
short s = 0x3210;
char* c = (char*)&s; // where c1 = c[0] and c2 = c[1]
那么将一个单词分成两个字节的最快方法是什么?
short s = 0x3210;
char c1 = s >> 8;
char c2 = s & 0x00ff;
相对
short s = 0x3210;
char c1 = s >> 8;
char c2 = (s << 8) >> 8;
怎么样
short s = 0x3210;
char* c = (char*)&s; // where c1 = c[0] and c2 = c[1]
让编译器为您完成这项工作。使用union
,其中字节将在没有任何手工位移的情况下被拆分。看伪代码:
union U {
short s; // or use int16_t to be more specific
// vs.
struct Byte {
char c1, c2; // or use int8_t to be more specific
}
byte;
};
用法很简单:
U u;
u.s = 0x3210;
std::cout << u.byte.c1 << " and " << u.byte.c2;
这个概念很简单,之后您可以根据需要重载运算符以使其更花哨。
重要的是要注意,根据您的编译器,顺序c1
可能c2
会有所不同,但这将在编译之前知道。您可以设置一些条件宏以确保顺序符合您在任何编译器中的需要。
在几乎所有架构中,我 99.9% 确信第一个至少与第二个一样快。可能有一些架构没有区别(它们是相等的),而在几种架构中,后者会更慢。
我说第二个比较慢的主要原因是有两个班次来计算这个c2
数字。处理器在完成第一个班次之前不能开始处理第二个班次。
此外,编译器很可能能够用第一个做其他聪明的事情(如果有指令可以做到这一点 - 例如 x86 处理器可以加载s
到 AX,并将 AL 存储到c1
AH 到c2
- 除了存储之外没有额外的指令操作),其中第二个不太可能是“已知的常见模式”(我当然从未见过在代码中使用该变体,该shift/and
方法非常常用 - 通常在“像素循环”中,这意味着它很关键对其进行良好的优化)。
和往常一样,测量,测量,再测量。除非您只对您的特定机器性能感兴趣,否则请在不同型号/处理器制造商上进行尝试,这样您就不会在您的机器型号上制造速度快 5% 的东西,但在另一个型号上却慢 20%。
您当然应该使用强制转换而不是掩码或两次移位来提取低位字节。然后编译器将执行它已经知道最快的任何事情。这给你留下了高位,只有一个选择。
您应该将它们中的每一个都计时在一个for (long i = 0; i < 100000000; i++)
. 我做到了,第一个更快(0.82s 对 0.84s)。在 MVS 中这样做的一个简单方法是在@clk
.