Delphi常量位运算表达式

6

可能是一个愚蠢的问题,但对我来说只是一种好奇。

我有一些Delphi代码看起来像这样;

const
  KeyRepeatBit = 30;
... // 如果lParam的第30位被设置,将此消息标记为已处理 if (Msg.lParam and (1 shl KeyRepeatBit) > 0) then Handled:=true; ...

(代码的目的并不重要)

编译器是否将"(1 shl KeyRepeatBit)"视为可以在编译时计算的内容,因此它变成了一个常量?如果不是,通过计算出一个数字并替换表达式中的数字,能获得任何收益吗?

5个回答

7

是的,编译器在编译时评估表达式,并使用结果值作为常数。自己声明另一个具有相同结果值的常量是没有意义的。

编辑:The_Fox 是正确的。可赋值类型的常量(参见 {$J+} 编译器指令)不被视为常量,在这种情况下表达式会在运行时评估。


你忘记了可写常量 ;) 在这种情况下,表达式会在运行时计算。 - The_Fox

4

您可以像这样确保可读性:

const
  KeyRepeatBit = 30;
  KeyRepeatMask = 1 shl KeyRepeatBit ;

为什么不使用 KeyRepeatMask = 1 shl KeyRepeatBit? - RobS

3
它将在编译时将其转换为常量。即使它没有这样做,这也不会对应用程序的性能产生明显影响。如果你的应用程序很繁忙,你可能每秒处理几千个消息。即使是你的旧 Pentium I 也可以每秒执行无数次移位和按位与操作。保持代码可读,并通过分析来找到需要优化的瓶颈 - 通常是查看算法,而不是像是否进行移位这样的低级别操作。

2

我怀疑在这里使用一个数字(顺便说一下,应该是1073741824)是否会真正提高性能。你似乎处于某个Windows消息上下文中,这可能会比一个单一的数字添加更多的延迟,而这个数字即使在编译时没有被优化(不过我认为已经被优化了),也是非常快的。

唯一我能想象到的例外情况是这段代码被运行得非常频繁,但正如我所说,我认为它在编译时已经被优化了,因此即使在这种情况下,它也不会有任何区别。


1
也许这与你的问题无关,但我在这类情况下使用案例记录,例如:

  TlParamRecord = record
    case Integer of
      0: (
        RepeatCount: Word;
        ScanCode: Byte;
        Flags: Set of (lpfExtended, lpfReserved=4, lpfContextCode,
          lpfPreviousKeyState, lpfTransitionState);
      );
      1: (lParam: LPARAM);
  end;

更多细节请参阅我博客上的文章


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接