我在 /usr/include/limits.h 中找到了以下定义:
# define INT_MIN (-INT_MAX - 1)
# define INT_MAX 2147483647
此外,这个头文件中的所有 XXX_MAX 似乎都是从一个数字常量显式定义的。
我想知道是否有一种可移植的方式(针对跨平台的不同字长)来定义 INT_MAX ?
我尝试了以下方法:
~((int)-1)
但这似乎不正确。
简短的解释也受到高度重视。
对于INT_MAX
标准 header中的 ,实现者的双手被要求在预处理器指令limits.h
中可用的事实束缚住了。#if
这排除了任何涉及sizeof
或演员的事情。
如果您只想要一个适用于实际 C 表达式的版本,也许这会起作用:
(int)-1U/2 == (int)(-1U/2) ? (int)-1U : (int)(-1U/2)
这里的概念是int
可能具有与 相同数量的值位unsigned
,或者少一个值位;C标准允许。为了测试它是什么,请检查转换的结果(int)-1U
。如果-1U
适合int
,则其值必须通过强制转换保持不变,因此等式将成立。如果-1U
不适合int
,则强制转换会导致实现定义的类型结果int
。但是,无论值是什么,仅根据可能值的范围,相等性将是错误的。
请注意,从技术上讲,转换为int
可能会导致引发实现定义的信号,而不是获得实现定义的值,但是当您处理将被评估为的常量表达式时,这不会发生编译时。
我喜欢这些定义:
#define INT_MIN (1 << (sizeof(int)*CHAR_BIT-1))
#define INT_MAX (-(INT_MIN+1))
不,因为没有可移植的方法来知道int
和之间的值位数的差异unsigned
。
有一种可移植的方式来获取UINT_MAX
,-1u
因为无符号整数是模类型。因此,表达式INT_MAX
为
(int)(UINT_MAX >> (value_bits<unsigned> - value_bits<int>))
可惜没有办法得到value_bits<unsigned> - value_bits<int>
。
在 C++ 中,这似乎可以通过模板元编程实现,从 15 位开始递归。(范围 [-32767, 32767] 保证可以用 表示int
。)
template<int bits>
struct max0
{
static const int value = max0<bits - 1>::value * 2 + 1;
};
template<>
struct max0<15>
{
static const int value = 32767;
};
template<int bits>
struct max1
{
static const int value =
max0<bits + 1>::value > max0<bits>::value ?
max1<bits + 1>::value :
max0<bits>::value;
};
#define INT_MAX (max1<15>::value)
但我觉得这有点矫枉过正,坚持编译器定义的__INT_MAX__
;(
编辑:哎呀!
max.cpp: In instantiation of 'const int max0<32>::value':
max.cpp:17:51: recursively required from 'const int max1<16>::value'
max.cpp:17:51: required from 'const int max1<15>::value'
max.cpp:28:28: required from here
max.cpp:4:52: warning: integer overflow in expression [-Woverflow]
static const int value = max0<bits - 1>::value * 2 + 1;
~~~~~~~~~~~~~~~~~~~~~~^~~
max.cpp:4:22: error: overflow in constant expression [-fpermissive]
static const int value = max0<bits - 1>::value * 2 + 1;
^~~~~
max.cpp:4:22: error: overflow in constant expression [-fpermissive]
max.cpp:4:22: error: overflow in constant expression [-fpermissive]
max.cpp: In instantiation of 'const int max0<914>::value':
max.cpp:17:51: recursively required from 'const int max1<16>::value'
max.cpp:17:51: required from 'const int max1<15>::value'
max.cpp:28:28: required from here
max.cpp:4:52: fatal error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum)
static const int value = max0<bits - 1>::value * 2 + 1;
~~~~~~~~~~~~~~~~~~~~~~^~~
compilation terminated.
嗯,可以试试
#define INT_MAX (int) ((unsigned) -1 / 2)
哪个“应该”跨平台工作,字长不同,甚至有符号整数值的不同表示。(unsigned) -1
将可移植地产生该UINT_MAX
值,即全位模式。将其除以 2 应成为相应有符号整数类型的预期最大值,该值用于表示符号的位。
但为什么?标准头文件和其中的定义不应该是可移植的。
顺便说一句,INT_MIN
你上面引用的定义是不可移植的。它特定于有符号整数的 2 的补码表示。
如果我们假设 1 或 2 的补码表示法和 8 位/字节且没有填充:
#define INT_MAX ((1 << (sizeof(int)*8 - 2)) - 1 + (1 << (sizeof(int)*8 - 2)))
我没有看到班次或加班有任何溢出。我也没有看到UB。我想一个可以使用CHAR_BIT
而不是 8。
在 1 和 2 的恭维中,最大 int 将是power(2,(sizeof(int)*Bits_per_byte - 1) - 1
. 我们将使用转变而不是权力,但我们不能一次转变太多。所以我们power(2,(sizeof(int)*Bits_per_byte - 1)
通过两次做一半来形成。但是溢出是一个禁忌,所以在添加第二半之前减去 1 而不是在末尾。我用了很多()
来强调评估顺序。
正如@caf 所指出的,这种方法失败是因为有填充位 - 不常见但可能。
计算 INT_MIN 在 2和1 的恭维中工作有点棘手,但类似的方法也可以,但这是另一个问题。