【问题标题】:Type safety and NEG instruction类型安全和 NEG 指令
【发布时间】:2015-06-12 11:54:39
【问题描述】:

我需要移植这个汇编指令:

NEG eax

所以我做了以下操作:

uint32_t a = 0x1234568;
a = reinterpret_cast<uint32_t>(-a);

因为reinterpret_cast 做了我想做的事,这意味着直接解释字节而不需要任何类型的转换/转换。

  • 我需要reinterpret_cast 来实现这个目的吗?
  • 这是否违反严格别名?
  • 如果我做错了,最好的实施方法是什么?

我问这个问题是因为虽然代码显然可以在 gcc 下运行,但它在 Visual Studio 下不起作用(cannot convert from uint32_t to uint32_tunary minus operator applied to unsigned type, result still unsigned)。这些错误是有道理的,但我不确定如何以不同的方式完成它,除了使用 bit hacks 计算 2 的互补。

【问题讨论】:

  • 我希望它计算 2 的补码(与 NEG 的方式相同),即获取存储为负整数的相同值的二进制等价物。请注意,它与仅翻转所有位的NOT 指令不同。
  • 特别想避免手动操作like this.
  • 除非我误解了标准,否则reinterpret_cast 是未定义的,不是由于严格的别名违规,而是因为未定义转换本身。在这个草案open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3225.pdf - 5.2.10 - 没有提到从有符号整数类型到无符号整数类型的转换。特别注意“无法使用 reinterpret_cast 显式执行其他转换”

标签: c++ binary opcode


【解决方案1】:
  • 这里不需要reinterpret_caststatic_cast就足够了。
  • 您的代码不适用于指针,因此不存在别名问题。
  • 结论:这种方法没有错。

顺便说一句:您的代码确实可以编译为“neg”指令,至少在英特尔平台上是这样。 ;-)


更新:

C++ 语言规范说:

一元 - 运算符的操作数应具有算术或枚举类型,结果是其操作数的否定。对整数或枚举操作数执行整数提升。无符号量的负数是通过从 2n 中减去其值来计算的,其中 n 是提升操作数中的位数。结果的类型是提升的操作数的类型。

并且由于无符号类型被提升为它们自己,一元减号可以应用于无符号类型并且不会改变它们。

所以这样写就对了,例如:

uint32_t convert( uint32_t x ) {
    return -x;
}

static_cast 可以在那里使用,但不是必需的。 reinterpret_cast 不能用于整数转换。

【讨论】:

  • 谢谢!只是为了确定:所以可以使用static_cast&lt;uint32_t&gt;(-static_cast&lt;int32_t&gt;(x));? (没有这些,VS 仍然会抱怨 - on unsigned 仍然是未签名的。)
  • “static_cast 就足够了”static_cast 总是更复杂或等同于reinterpret_cast,所以它没有意义。
  • @ElderBug 从最不激进的类型转换开始总是更好,请参阅stackoverflow.com/questions/332030/…
  • @ElderBug reinterpret_cast 无法使用,因为它无法将无符号整数类型转换为其有符号等效值(反之亦然)。我不清楚你为什么声称static_cast“没有意义”。 (我同意虽然说static_cast 是“足够的”是不对的。事实上,static_cast必要的)。
  • @ElderBug “这里的重点是不要转换” - 但是否定会产生一个有符号整数,必须将其转换回无符号整数。除非避免否定,否则转换是必要的。 “而 reinterpret_cast 完全可以用来从无符号转换为有符号,不知道你在说什么” - 不,它不能;我说的是标准所说的,以及我测试的编译器(g++ 4.6.3)符合什么。新版本的标准有什么变化吗?
【解决方案2】:

我会使用a = 0 - a;。或者您可以使用a = -a;,但它可能会发出编译警告。警告不是错误,但应该避免。

你也可以试试内联汇编。

mov eax, a
neg eax
mov a, eax

【讨论】:

    猜你喜欢
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-03
    • 2016-10-15
    • 2014-04-13
    • 1970-01-01
    相关资源
    最近更新 更多