我的印象和this answer一样,size_t
始终由标准保证足够大以容纳给定系统的最大可能类型。
但是,这段代码无法在 gcc/Mingw 上编译:
#include <stdint.h>
#include <stddef.h>
typedef uint8_t array_t [SIZE_MAX];
error: size of array 'array_t' is too large
我是不是误解了标准中的某些内容?对于给定的实现,size_t
是否允许太大?或者这是 Mingw 中的另一个错误?
编辑:进一步的研究表明
typedef uint8_t array_t [SIZE_MAX/2]; // does compile
typedef uint8_t array_t [SIZE_MAX/2+1]; // does not compile
恰好与
相同#include <limits.h>
typedef uint8_t array_t [LLONG_MAX]; // does compile
typedef uint8_t array_t [LLONG_MAX+(size_t)1]; // does not compile
所以我现在倾向于认为这是 Mingw 中的一个错误,因为根据有符号整数类型设置最大允许大小没有任何意义。
最佳答案
SIZE_MAX/2 的限制来自您实现中的 size_t 和 ptrdiff_t 的定义,它们选择类型 ptrdiff_t 和 size_t 具有相同的宽度。
C 标准要求1类型 size_t 是无符号的,类型 ptrdiff_t 是有符号的。
两个指针之间的差异结果,总是2 具有 ptrdiff_t 类型。这意味着,在您的实现中,对象的大小必须限制为 PTRDIFF_MAX,否则无法在类型 ptrdiff_t 中表示两个指针的有效差异,从而导致未定义的行为。
因此值 SIZE_MAX/2 等于值 PTRDIFF_MAX。如果实现选择最大对象大小为 SIZE_MAX,则必须增加类型 ptrdiff_t 的宽度。但是将对象的最大大小限制为 SIZE_MAX/2 要容易得多,那么就是让类型 ptrdiff_t 的正范围大于或等于类型 size_t。
Standard 提供关于该主题的这些3 条评论4。
(引自 ISO/IEC 9899:201x)
1(7.19常用定义2)
类型是
ptrdiff_t
是两个指针相减结果的有符号整数类型;
大小_t
sizeof运算结果的无符号整数类型;
2(6.5.6加法运算符9)
当两个指针相减时,都应指向同一个数组对象的元素,
或数组对象最后一个元素之后的一个;结果是
两个数组元素的下标。结果的大小是实现定义的,
其类型(有符号整数类型)是 header 中定义的 ptrdiff_t。
如果结果在该类型的对象中不可表示,则行为未定义。
3(K.3.4 整数类型 3)
非常大的物体尺寸通常表明物体的尺寸是经过计算的
不正确。例如,负数在以下情况下显示为非常大的正数
转换为无符号类型,如 size_t。此外,某些实现不支持
与 size_t 类型可以表示的最大值一样大的对象。
4(K.3.4 整数类型 4)
由于这些原因,有时限制对象大小的范围以检测是有益的
编程错误。对于针对具有大地址空间的机器的实现,
建议将 RSIZE_MAX 定义为最大尺寸中的较小者
支持的对象或 (SIZE_MAX >> 1),即使此限制小于
一些合法但非常大的物体。针对小型机器的实现
地址空间可能希望将 RSIZE_MAX 定义为 SIZE_MAX,这意味着没有对象大小被视为运行时约束违规。
关于c - 为什么数组的最大大小是 "too large"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42574890/