4

那么将一个单词分成两个字节的最快方法是什么?

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]
4

4 回答 4

7

让编译器为您完成这项工作。使用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会有所不同,但这将在编译之前知道。您可以设置一些条件宏以确保顺序符合您在任何编译器中的需要。

于 2013-07-25T11:31:19.577 回答
6

在几乎所有架构中,我 99.9% 确信第一个至少与第二个一样快。可能有一些架构没有区别(它们是相等的),而在几种架构中,后者会更慢。

我说第二个比较慢的主要原因是有两个班次来计算这个c2数字。处理器在完成第一个班次之前不能开始处理第二个班次。

此外,编译器很可能能够用第一个做其他聪明的事情(如果有指令可以做到这一点 - 例如 x86 处理器可以加载s到 AX,并将 AL 存储到c1AH 到c2- 除了存储之外没有额外的指令操作),其中第二个不太可能是“已知的常见模式”(我当然从未见过在代码中使用该变体,该shift/and方法非常常用 - 通常在“像素循环”中,这意味着它很关键对其进行良好的优化)。

和往常一样,测量,测量,再测量。除非您只对您的特定机器性能感兴趣,否则请在不同型号/处理器制造商上进行尝试,这样您就不会在您的机器型号上制造速度快 5% 的东西,但在另一个型号上却慢 20%。

于 2013-07-25T11:19:53.440 回答
1

您当然应该使用强制转换而不是掩码或两次移位来提取低位字节。然后编译器将执行它已经知道最快的任何事情。这给你留下了高位,只有一个选择。

于 2013-07-25T11:33:24.307 回答
1

您应该将它们中的每一个都计时在一个for (long i = 0; i < 100000000; i++). 我做到了,第一个更快(0.82s 对 0.84s)。在 MVS 中这样做的一个简单方法是在@clk.

于 2013-07-25T12:14:19.227 回答