Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么数组的最大大小是;太大了;?_C_Gcc_Mingw_Size T_Stdint - Fatal编程技术网

C 为什么数组的最大大小是;太大了;?

C 为什么数组的最大大小是;太大了;?,c,gcc,mingw,size-t,stdint,C,Gcc,Mingw,Size T,Stdint,我的印象是,size\u t始终由标准保证足够大,以容纳给定系统的最大可能类型 但是,此代码无法在gcc/Mingw上编译: #include <stdint.h> #include <stddef.h> typedef uint8_t array_t [SIZE_MAX]; 这恰好与 #include <limits.h> typedef uint8_t array_t [LLONG_MAX]; // does compile ty

我的印象是,
size\u t
始终由标准保证足够大,以容纳给定系统的最大可能类型

但是,此代码无法在gcc/Mingw上编译:

#include <stdint.h>
#include <stddef.h>

typedef uint8_t array_t [SIZE_MAX];
这恰好与

#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
#包括
typedef uint8_t数组[LLONG_MAX];//编译
typedef uint8_t数组[LLONG_MAX+(size_t)1];//不编译

因此,我现在倾向于认为这是Mingw中的一个缺陷,因为基于有符号整数类型设置允许的最大大小没有任何意义。

仅从零开始推理,
size\u t
是一种可以容纳任何对象大小的类型。任何对象的大小都受到地址总线宽度的限制(忽略多路复用和可以处理例如32位和64位代码的系统,称之为“代码宽度”)。不知道
MAX\u INT
是最大整数值,
SIZE\u MAX
SIZE\u t
的最大值。因此,大小为
size\u MAX
的对象都是可寻址内存。实现将其标记为错误是合理的,但是,我同意只有在实际对象被分配的情况下才是错误,无论是在堆栈上还是在全局内存中。(无论如何,调用
malloc
获取该金额都将失败)

它看起来非常像特定于实现的行为

我在这里运行Mac OS,使用gcc 6.3.0,我可以编译您定义的最大大小是
size_MAX/2
;使用
SIZE\u MAX/2+1
它不再编译


另一方面,witch clang 4.0.0最大的一个是
SIZE\u MAX/8
,并且
SIZE\u MAX/8+1
中断。

限制大小\u MAX/2来自于实现中的SIZE\u t和ptrdiff\u t的定义,它们选择类型ptrdiff\u t和SIZE\u t具有相同的宽度

C标准要求1类型大小为无符号,类型ptrdiff为有符号

两个指针之间的差异结果将始终具有类型ptrdiff_t。这意味着,在您的实现中,对象的大小必须限制为 PTRDIFF_MAX,否则在类型PTRDIFF_t中无法表示两个指针的有效差异,从而导致未定义的行为

因此,值SIZE_MAX/2等于值PTRDIFF_MAX。如果实现选择将最大对象大小设置为SIZE_MAX,则必须增加类型PTRDIFF_t的宽度。但是,将对象的最大大小限制为size_MAX/2要容易得多,然后让类型ptrdiff_t的正范围大于或等于类型size_t的正范围

《标准》提供了关于该主题的3条评论


(引自ISO/IEC 9899:201x)

1(7.19通用定义2)
类型为
ptrdiff\u t
它是减去两个指针的结果的有符号整数类型
大小\u t
它是sizeof运算符结果的无符号整数类型

2(6.5.6加法运算符9)
减去两个指针时,两个指针都应指向同一数组对象的元素, 或超过数组对象最后一个元素一次;结果是两个参数的差异 两个数组元素的下标。结果的大小由实现定义, 并且其类型(有符号整数类型)是在头中定义的ptrdiff_t。 如果结果不能在该类型的对象中表示,则行为是未定义的

3(K.3.4整数类型3)
超大的对象大小通常是计算对象大小的标志 不对。例如,负数在以下情况下显示为非常大的正数: 已转换为大小\u t之类的无符号类型。此外,一些实现不支持 与类型大小\u t表示的最大值一样大的对象

4(K.3.4整数类型4)
出于这些原因,限制要检测的对象大小范围有时是有益的 编程错误。对于针对具有大地址空间的计算机的实现, 建议将RSIZE_MAX定义为最大尺寸中的较小值 支持的对象或(大小\u MAX>>1),即使此限制小于 一些合法但非常大的物体。针对小型计算机的实现
地址空间可能希望将RSIZE_MAX定义为SIZE_MAX,这意味着不存在被视为违反运行时约束的对象大小。

保证
SIZE_t
的范围足以存储实现支持的最大对象的大小。反之则不然:不能保证您能够创建一个对象,该对象的大小可以填充整个
size\u t
范围

在这种情况下,问题是:
SIZE\u MAX
代表什么?支持的最大对象大小?或可在
大小\u t
中表示的最大值?答案是:它是后者,即
SIZE\u MAX
(SIZE\u t)-1
。不能保证您能够创建大字节的对象
SIZE\u MAX
bytes

这背后的原因是,除了
size\u t
,实现还必须提供
ptrdiff\u t
,其目的是(但不保证)存储指向同一数组对象的两个指针之间的差异。由于类型
ptrdiff\u t
已签名,因此实现面临以下选择:

  • 允许大小为
    size\u MAX
    的数组对象,并使
    ptrdiff\u t
    size\u t
    宽。它必须至少宽一点。这样的
    ptrdiff\u t
    可以容纳指向大小
    size\u MAX
    或更小数组的两个指针之间的任何差异

  • 允许大小为
    size\u MAX
    的数组对象,并使用与
    size\u t
    宽度相同的
    ptrdiff\u t
    。接受p
    #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