我需要在不使用 INT32_MAX、INT_MAX 等常量的情况下找到最大 int32_t 数字

I need to find maximum int32_t number without using constants like INT32_MAX, INT_MAX, etc

所以我有一个任务是在添加两个 int32_t 数字时检查溢出。在溢出的情况下,我的函数必须 return 最大或最小数量 int32_t,具体取决于溢出的符号,但使用像 UINT32_MAX 这样的常量是受限制的。我怎么做?如果对您有帮助,请参考以下代码:

#include "inttypes.h"

int32_t
satsum(int32_t v1, int32_t v2) {
    int32_t res = 0;
    if(__builtin_sadd_overflow(v1, v2, &res)) {
        if (res < 0) {
            return ?
        }
        return ?
    } else {
        res = v1 + v2;
        return res;
    }
}

INT32_MAX的值(int32_t的最大值)和INT32_MINint32_t的最小值)在C规范中定义,所以你可以写值而不是使用常量。

引自N1570 7.20.2.1 精确宽度整数类型的限制:

— minimum values of exact-width signed integer types
INTN_MIN exactly −(2N-1)
— maximum values of exact-width signed integer types
INTN_MAX exactly 2N−1 − 1
— maximum values of exact-width unsigned integer types
UINTN_MAX exactly 2N − 1

这里有一点:2N可以表示为1<<N,但是1<<31会造成溢出,所以应该用((1<<30)-1)*2+1 而不是 1<<31.

您还应该使用 INT32_C macor 来使用 int32_t 的文字而不是 int.

总之,您应该使用的是:

  • 最大值int32_t((INT32_C(1)<<30)-1)*2+1
  • int32_t的最小值:-((INT32_C(1)<<30)-1)*2-2

int32_t 保证为 2 的补码形式。这意味着最大值保证为2^31 -1,最小值保证为-2^31.

所以你可以简单地这样做:

const int32_t i32_min = 1u << 31;
const int32_t i32_max = (1u << 31)-1u;

此代码将导致实现定义的从无符号到有符号的转换,在这种情况下意味着转换将采用 2 的补码格式。