【发布时间】:2016-11-29 18:31:17
【问题描述】:
我很惊讶 VisualStudio 2015 坚持将 WORD (unsigned short) 提升为 unsigned int,而只有 WORD 值仅涉及位操作。 (即在做 16bit | 16bit 时将 16 位提升到 32 位)。
例如
// where WORD is a 'unsigned short'
const WORD kFlag = 1;
WORD old = 2;
auto value = old | kFlag; // why the blazes is value an unsigned int (32 bits)
此外,有没有办法为WORD|WORD 获取 0x86 内在函数?我当然不想为 (16->32|16->)->16 付费。这段代码也不需要消耗超过几个 16 位寄存器,而不是几个 32 位寄存器。
但注册表的使用实际上只是一个旁白。欢迎优化器为所欲为,只要结果对我来说是无法区分的。 (即它不应该以可见的方式改变大小)。
对我来说主要的问题是使用 flags|kFlagValue 会产生更宽的实体,然后将其泵入模板会给我一个类型不匹配错误(模板比我想在这里输入的要长得多,但重点它是否需要两个参数,并且它们应该在类型上匹配,或者可以简单地转换,但由于这个自动大小提升规则,它们不是)。
如果我可以访问“保守位处理功能集”,那么我可以使用:
flag non-promoting-bit-operator kFlagValue
为了达到我的目的。
由于这条不幸的规则,我想我必须去写它,或者到处使用强制转换。
C++ 在这种情况下不应该提升。这是一个糟糕的语言选择。
【问题讨论】:
-
如果这个函数的输出对你的程序的整体执行非常重要,那么一定要把一些汇编器放在那里,帮助编译器正确地完成它。否则,如果香肠味道还不错,何必担心香肠里有什么?
-
因为它违反了类型。 C++ 正在扩大一些永远不应该扩大的东西。与其他 16 位值进行 OR 或 AND 运算的 16 位值永远不会溢出,结果是可以存储在 ABI 中的 100% 安全的 16 位值。我不希望该语言以产生明显副作用的方式任意提升速度,而这些副作用不需要任何东西(如果它想这样做作为一种对我来说不可见的优化,那很好,但这会产生明显的后果强制我的代码必须更改):(
-
逻辑运算,算术运算的子集,将小于
int的操作数转换为int -
如果您将值声明为 WORD,那么编译器可能会对其进行优化。如果您使用 auto 则不是这种情况,因为标准要求进行升级。
-
是的,但它会破坏模板——它们会生成愚蠢的代码,因为操作数的类型不同。 (是的,这个例子是涉及模板的更一般情况的一个子集)。
标签: c++ bitwise-operators integer-promotion