壳牌算法说:
评估是在固定宽度的整数中完成的,不检查溢出,但除以 0 会被捕获并标记为错误。
例子:
$ echo $(( 1 << 32 ))
4294967296
$ echo $(( (1 << 64) - 1 ))
0
Run Code Online (Sandbox Code Playgroud)
bash中shell算术的整数限制是什么?
@rici指出的是POSIX壳保证符号长整数范围(如由ISO C定义):
-2**31+1 to +2**31-1
Run Code Online (Sandbox Code Playgroud)
@约翰Zwinck指出该bash源代码指示intmax_t用于:
所有算术都作为
intmax_t整数完成,不检查溢出
bash 是否在其文档中保证它使用intmax_t或其他一些 C 类型的整数?
Bash 没有记录整数的精确大小,并且大小可能因平台而异。
然而,它确实尝试符合 Posix,Posix 规定算术扩展使用有符号长算术,包括符号位在内必须至少为 32 位。
Posix 不要求整数算术对任何值以 2 kk为模[但请参阅注释 1],尽管bash在常见平台上会这样做,并且它特别不保证算术运算符的行为与这些值是有符号长整型完全一样。Posix 甚至允许用浮点模拟整数运算,前提是浮点值具有足够的精度:
作为扩展,shell 可以识别超出列出的算术表达式。shell 可以使用有符号整数类型,其等级大于有符号长整数的等级。shell 可以使用实数浮点类型而不是有符号长整型,只要在没有溢出的情况下不影响结果即可。(XSH §2.6.4)
long例如,这将允许在只有 32 位的平台上使用 IEEE-754 浮点双精度(53 位精度) 。虽然bash没有这样做(如文档所述,bash使用固定宽度整数数据类型),但其他 shell 实现可能会这样做,并且可移植代码不应做出假设。
笔记:
Posix 一般遵循 ISO C 标准,但有很多地方 Posix 添加了额外的约束,其中一些被标记为扩展 ( CX):
POSIX.1-2008 部分充当 ISO C 标准的概要,并且它可以选择进一步限制 ISO C 标准允许变化的行为。即使缺少 CX 标记,此类限制和其他兼容差异也不被视为冲突。这些标记仅供参考。
这些附加约束之一是精确宽度整数类型的存在。标准 C 需要类型int_{least,fast}{8,16,32,64}_t及其无符号类似物。它不需要精确宽度类型,例如int32_t,除非某些整数类型符合要求。精确宽度类型必须具有与其名称中指示的位数完全相同的位数(即无填充位),并且必须具有 2 的补码表示形式。因此INT32_MIN,如果已定义,则 必须恰好为 -2 31 (§7.20.2.1)。
然而,Posix确实需要精确宽度类型int{8,16,32}_t(以及无符号类似物),并且还int64_t需要实现提供这样的类型。特别是,int64_t如果“实现支持_POSIX_V7_LP64_OFF64编程环境并且应用程序正在_POSIX_V7_LP64_OFF64编程环境中构建”,则需要这样做。(XBD,§13,stdint.h)(这些要求标记为CX。)
尽管它int32_t必须存在,因此必须有一些 2 的补码类型可用,但仍然不能保证它signed long是 2 的补码,即使是,也不能保证整数溢出回绕而不是,例如,诱捕。
不过,与最初的问题最相关的是,即使 与signed long类型相同,int64_t并且即使有符号整数溢出回绕,shell 也没有任何义务实际用于signed long算术扩展。它可以使用任何数据类型,“只要它在没有溢出的情况下不影响结果”。(XSH,§2.6.4)