Bash没有记录整数的确切大小,并且大小可能因平台而异。
但是,它确实试图符合Posix,它指定算术扩展使用带符号的长算术,它必须至少包含32位(包括符号位)。
的Posix不需要整数运算是模2 ķ为k
任何值,但见注1],虽然bash
共同平台将这样做,而且特别不保证算术运算符的行为完全就好像这些值是经过长时间签名的。 Posix甚至允许使用浮点模拟整数运算,前提是浮点值具有足够的精度:
作为扩展,shell可以识别超出列出的算术表达式。 shell可能使用一个有符号整数类型,其排名大于signed long的排名。在没有溢出的情况下,只要不影响结果,shell可以使用真实浮点型而不是长整型。 (XSH § 2.6.4)
这将允许一个平台,long
仅为32位,例如在使用IEEE-754浮点数的加倍(精度53位)。虽然bash
不这样做 - 正如文档中所述,bash
使用固定宽度的整数数据类型 - 其他shell实现可能会和可移植代码不应做出假设。
注:
的Posix通常推迟到ISO C标准,但也有一些地方的Posix增加了一个附加的约束,其中的一些被标记为扩展(CX):
POSIX.1-2008部分地作为ISO C标准的一部分,它可以选择进一步构建ain行为允许根据ISO C标准而变化。即使缺少CX标记,这些限制和其他兼容差异也不会被视为冲突。标记仅供参考。
其中一个附加约束是存在精确宽度的整数类型。标准C要求类型int_{least,fast}{8,16,32,64}_t
及其无符号类似物。它不需要精确宽度类型,例如int32_t
,除非某些整数类型符合要求。精确宽度类型必须正好具有其名称中指示的位数(即没有填充位),并且必须具有2的补码表示。因此INT32_MIN
,如果已定义,则必须正好-2 (§ 7.20.2.1)。
然而,Posix的确实需要的确切宽类型int{8,16,32}_t
(以及无符号类似物),并且也int64_t
如果这样的类型是由实现提供。特别是,如果“实现支持_POSIX_V7_LP64_OFF64
编程环境并且应用程序正在编程环境中构建,则需要int64_t
”。 (XBD,§ 13,stdint.h
)(这些要求都被标记为CX。)
尽管int32_t
必须存在,因此必须有一些2的补码型可用的事实,但仍然没有保证signed long
是2的补码,即使是这样,也不能保证整数溢出回绕,而不是例如陷阱。
最为相关的原题,虽然是事实,即使signed long
是同一类型int64_t
即使有符号整数溢出环绕,外壳是没有根据实际使用signed long
的算术扩展的任何义务。它可以使用任何数据类型“只要在没有溢出的情况下不影响结果”。 (XSH,§ 2.6.4)
我不认为在飞越(!)后减1(!)将有助于:-)尝试echo $(((1 << 63) - 1)).. 9223372036854775807 – 2014-09-30 13:09:11
@MarkSetchell:关键是我的机器上有'1 << 64'溢出。在这种情况下结果并不重要。 – jfs 2014-09-30 13:10:14
我曾幻想你在做一个二进制搜索以找到没有溢出的移位... << 48,<< 56,<< 60, – 2014-09-30 13:12:18