c - 为什么数组的最大大小是 "too large"?

标签 c gcc mingw size-t stdint

我的印象和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/

相关文章:

c - 使用notepad++和minGW编译时缺少.dll文件

c++ - 链接本身依赖于静态库的自己的静态库时的 undefined reference

c++ - C 函数 'void msgBox(const char*, const char*)' 的声明与之前的声明冲突

c - 使用 C 的某些示例的 Base64 解码不正确

c - C中的套接字编程

c - 检测预处理器宏中的空参数

c - Unix 中的 Strace 命令

c - 在 C 上使用 pthreads 实现屏障

c++ - QNX QCC 链接器包括文件时间戳

linux - 不能使用 g++ 进行编译