简体   繁体   English

有没有办法让32位C ++编译器遵循16位整数提升规则?

[英]Is there a way to get a 32bit C++ compiler to follow 16bit integer promotion rules?

With the following code: 使用以下代码:

#include <stdint.h>

uint16_t test() {
    uint16_t a = 1000;
    uint16_t b = 1000;
    uint16_t c = 100;
    return (a * b) / c;
}

A compiler targeting a 32bit machine will return 10000, but one targeting a 16 bit machine will return 169. The behavior is explained by C's integer promotion rules. 针对32位机器的编译器将返回10000,但是针对16位机器的编译器将返回169.该行为由C的整数提升规则解释。

This is a problem when unit testing firmware for a 8 or 16 bit machine on a desktop PC. 当在台式PC上对8或16位机器进行单元测试时,这是一个问题。

Right now, either casting every multiplication or putting it inside a function returning the same type are the only options I can think of. 现在,要么将每次乘法转换或将其放入返回相同类型的函数中,这是我能想到的唯一选项。 Ideally some compiler switch would exist, but I haven't seen one. 理想情况下会存在一些编译器开关,但我还没有看到。

Happy with a solution for either GCC, Clang or MSVC. 对GCC,Clang或MSVC的解决方案感到满意。

This could be an XY problem . 这可能是一个XY问题 Depends on your specific work. 取决于您的具体工作。

While unit testing on a desktop machine for a different architecture could help, I doubt this is the way. 虽然针对不同架构的台式机上的单元测试可能有所帮助,但我怀疑这是方法。 Even if you found some switches in the compiler to simulate on x86 some rules for other architecture, you can never be sure that the simulated behavior will be the same as in the real environment. 即使你在编译器中发现了一些开关来在x86上模拟其他架构的一些规则,你仍然无法确定模拟的行为是否与真实环境中的相同。 Furthermore there certainly will be other differences (some you can predict, some you cannot) on behavior between the target architecture and the testing architecture. 此外,目标架构和测试架构之间的行为肯定会存在其他差异(有些可以预测,有些则无法预测)。

So in conclusion, testing on an architecture and expecting it to work on another is not reliable, not in a real way anyway. 总而言之,对架构进行测试并期望它在另一个架构上工作是不可靠的,无论如何都不是真实的。 So the solution should be to test on the target architecture. 所以解决方案应该是在目标架构上进行测试。 Get an emulator, or a VM, or a remote device on which you can unit test on the real environment. 获取可以在真实环境中进行单元测试的模拟器,VM或远程设备。

If that is not a viable option, instead of trying to make unit testing match the real environment from a pc environment, you could just live with these differences, take into account that unit tests are not very reliable and use them just for limited testing, and rely more on integration testing, which should be on the target architecture. 如果这不是一个可行的选择,而不是试图使单元测试与PC环境中的真实环境相匹配,那么您可以忍受这些差异,考虑到单元测试不是非常可靠并仅将它们用于有限的测试,并且更多地依赖于集成测试,这应该在目标架构上。

No, there isn't any way to do what you're asking. 不,没有办法做你要问的事。

Right now, either casting every multiplication or putting it inside a function returning the same type are the only options I can think of. 现在,要么将每次乘法转换或将其放入返回相同类型的函数中,这是我能想到的唯一选项。

Another option is avoiding using multiple operations in a single expression, implicitly forcing a conversion back to uint16_t : 另一种选择是避免在单个表达式中使用多个操作,隐式强制转换回uint16_t

uint16_t test() {
    uint16_t a = 1000;
    uint16_t b = 1000;
    uint16_t c = 100;
    a *= b;
    a /= c;
    return a;
}

Or, using a function, that function could be an overloaded operator to keep the code readable: 或者,使用函数,该函数可以是重载运算符以保持代码可读:

#include <stdint.h>

template <typename T>
struct unpromoted
{
   T value;

   unpromoted() = default;
   unpromoted(T value) : value(value) { }
   explicit operator T() { return value; }

   friend unpromoted operator*(unpromoted a, unpromoted b)
   { return a.value * b.value; }

   friend unpromoted operator/(unpromoted a, unpromoted b)
   { return a.value / b.value; }

   // add other operators as well
};

using uuint16_t = unpromoted<uint16_t>;

uuint16_t test() {
    uuint16_t a = 1000;
    uuint16_t b = 1000;
    uuint16_t c = 100;
    return (a * b) / c; // returns 169
}

Note that this does require a cast when eg adding an uuint16_t and an uuint8_t . 请注意,这需要在添加uuint16_tuuint8_t时进行uuint16_t uuint8_t It's possible to let that return an uuint16_t , but I probably wouldn't bother with it. 可以让它返回一个uuint16_t ,但我可能不会打扰它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM