相关: 这对int64_t的处理是GCC和Clang的错误吗?
我能想到的唯一解决方案是将其中一个操作数显式转换为int64,至少也要强制产品int64.
但是如果以这种方式完成,则由编译器的智能实际做到int64*int32,或者int64*int64,或者理想情况下,将其优化回来int32*int32.
如在相关问题讨论,分配的结果int32*int32,以int64不改变的事实int32*int32已经引起UB.
任何想法?
小智 9
您已经指出了如何以标准,便携和高效的方式执行此操作:
int64_t mul(int32_t x, int32_t y) {
return (int64_t)x * y;
// or static_cast<int64_t>(x) * y if you prefer not to use C-style casts
// or static_cast<int64_t>(x) * static_cast<int64_t>(y) if you don't want
// the integral promotion to remain implicit
}
Run Code Online (Sandbox Code Playgroud)
您的问题似乎是关于假设的体系结构,其具有与功能签名对应的汇编指令
int64_t intrinsic_mul(int32_t x, int32_t y);
int64_t intrinsic_mul(int64_t x, int64_t y);
int64_t intrinsic_mul(int64_t x, int32_t y); // and maybe this too
Run Code Online (Sandbox Code Playgroud)
并且,在这个假设的体系结构中,第一个具有相关优势,而且,在编译上述函数时,编译器无法使用此指令,并且最重要的是,它无法提供对上述内部函数的访问.
我希望这样的场景真的很少见,但是如果你真的发现自己处于这种情况,大多数编译器也允许你编写内联汇编,所以你可以编写一个直接调用这个特殊指令的函数,并且仍然提供足够的元数据优化器可以有效地使用它(例如使用符号输入和输出寄存器,因此优化器可以使用它想要的任何寄存器,而不是使寄存器选择硬编码).
内置算术表达式仅针对同类操作数类型退出.任何涉及混合类型的表达都意味着整体提升,并且算术操作本身只是为同类型定义并应用于同类型.
选择int32_t或者int64_t.
正如你可能正确地理解,对于整型算术运算的两个备选项(至少+,-和*)易受UB通过溢出,但在两个操作时不能有任何溢出int64_t这既可以表示为s int32_t秒.例如,以下工作:
int64_t multiply(int32_t a, int32_t b)
{
// guaranteed not to overflow, and the result value is equal
// to the mathematical result of the operation
return static_cast<int64_t>(a) * static_cast<int64_t>(b);
}
Run Code Online (Sandbox Code Playgroud)
例如,以下是GCC如何将其转换为Linux上的x86和x86_64(请注意不同的调用约定):
multiply(int, int):
// x86 (32-bit, "-m32 -march=i386") x86-64 ("-m64 -march=x86-64")
// args are on the stack args are in EDI, ESI
// return in EDX:EAX return in RAX
mov eax, DWORD PTR [esp+8] movsx rax, edi
movsx rsi, esi
imul DWORD PTR [esp+4] imul rax, rsi
ret ret
Run Code Online (Sandbox Code Playgroud)