Type safety and NEG instruction

200 views Asked by At

I need to port this Assembly instruction:

NEG eax

so I did following:

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

since reinterpret_cast does what I want, meaning interpreting bytes directly without any kind of casting/conversions.

  • Do I need reinterpret_cast for this purpose?
  • Does this violate strict aliasing?
  • If I do it wrong, what is the best way to implement it?

I'm asking this question because while the code apparently works under gcc, it doesn't work under Visual Studio (cannot convert from uint32_t to uint32_t and unary minus operator applied to unsigned type, result still unsigned). The errors make sense, but I'm not sure how can I do it in a different way except for computing 2's complementary using bit hacks.

2

There are 2 answers

11
dlask On BEST ANSWER
  • You don't need reinterpret_cast here, the static_cast is sufficient.
  • Your code doesn't work with pointers so there is no aliasing issue.
  • Conclusion: There is nothing wrong in this approach.

BTW: Your code really compiles to the "neg" instruction, at least on Intel platforms. ;-)


Update:

The C++ language specification says:

The operand of the unary − operator shall have arithmetic or enumeration type and the result is the negation of its operand. Integral promotion is performed on integral or enumeration operands. The negative of an unsigned quantity is computed by subtracting its value from 2n, where n is the number of bits in the promoted operand. The type of the result is the type of the promoted operand.

And since unsigned types are promoted to themselves, the unary minus can be applied to unsigned types and doesn't change them.

So it's correct to write, for example:

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

The static_cast can be used there but it is not needed. The reinterpret_cast cannot be used to convert integers.

0
ST3 On

I would use a = 0 - a;. Or you can have a = -a; however it may give compilation warning. Warning not an error, however it should be avoided.

Also you can try inline assembly.

mov eax, a
neg eax
mov a, eax