C中数组的最大大小是多少?

时间:2012-02-21 23:31:58

标签: c arrays

据我所知,硬件将限制程序执行期间分配的内存量。但是,我的问题是而不考虑硬件。假设内存量没有限制,那么阵列没有限制吗?

7 个答案:

答案 0 :(得分:39)

C中数组的大小没有固定的限制。

任何单个对象(包括任何数组对象)的大小都受SIZE_MAX的限制,size_t是类型sizeof的最大值,它是SIZE_MAX运算符的结果。 (目前还不完全清楚C标准是否允许大于SIZE_MAX个字节的对象,但实际上不支持这些对象;请参阅脚注。)由于SIZE_MAX由实现决定,因此无法修改任何程序,为任何单个对象强加void*个字节的上限。 (这是一个上限,而不是一个上限;实现可能,通常会,施加更小的限制。)

类型SIZE_MAX的宽度(通用指针类型)对执行程序中所有对象的总大小施加上限(可能大于单个对象的最大大小)。 / p>

C标准对这些固定大小施加下限但不上限。没有符合要求的C实现可以支持无限大小的对象,但它原则上可以支持任何有限大小的对象。上限是由单个C实现,它们运行的​​环境以及物理而不是语言强加的。

例如,一个一致的实现可以具有SIZE_MAX等于2 1024 -1,这意味着它可以原则上有对象高达179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137215个字节。

祝你找到真正支持此类对象的硬件。

脚注:没有明确的规则,任何对象都不能大于sizeof个字节。您无法将sizeof运算符应用于此类对象,但与任何其他运算符一样,size_t可能会溢出;这并不意味着你无法对这样的对象进行操作。但实际上,任何理智的实现都会使{{1}}大到足以表示它支持的任何对象的大小。

答案 1 :(得分:8)

C99 5.2.4.1"翻译限制"最小尺寸

  

实现应能够翻译和执行至少一个包含以下每个限制的至少一个实例的程序:13)

     
      
  • 对象中的65535个字节(仅限托管环境中)
  •   
     

13)实施应尽可能避免强加固定的翻译限制。

这表明符合标准的实现可以拒绝编译超过short字节的对象(包括数组)。

PTRDIFF_MAX似乎是静态数组对象的实际限制

C99标准 6.5.6添加剂运算符表示:

  

9当减去两个指针时,两个指针都指向同一个数组对象的元素,   或者超过数组对象的最后一个元素;结果是差异   两个数组元素的下标。结果的大小是实现定义的,   并且其类型(有符号整数类型)在ptrdiff_t标头中定义为<stddef.h>。   如果结果在该类型的对象中无法表示,则行为未定义。

这对我来说意味着理论上允许大于ptrdiff_t的数组,但是你不能以可靠的方式区分它们的地址。

也许出于这个原因,GCC似乎只限制你ptrdiff_t。在Why is the maximum size of an array "too large"?

中也提到了这一点

我已经凭main.c验证了这一点:

#include <stdint.h>

uint8_t a[(X)];

int main(void) {
    return 0;
}

然后在Ubunbu 17.10:

$ arm-linux-gnueabi-gcc --version
arm-linux-gnueabi-gcc (Ubuntu/Linaro 7.2.0-6ubuntu1) 7.2.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ printf '
> #include <stdint.h>
> PTRDIFF_MAX
> SIZE_MAX
> ' | arm-linux-gnueabi-cpp | tail -n2
(2147483647)
(4294967295U)
$ PTRDIFF_MAX == 2147483647 == 2^31 - 1
$
$ # 2lu << 30 == 2^31 == PTRDIFF_MAX + 1
$ arm-linux-gnueabi-gcc -std=c99 -DX='(2lu << 30)' main.c
a.c:5:9: error: size of array ‘a’ is too large
 uint8_t a[(X)];
         ^
$
$ # PTRDIFF_MAX
$ arm-linux-gnueabi-gcc -std=c99 -DX='(2lu << 30) - 1lu' main.c
$

另见

答案 2 :(得分:6)

64位机器理论上可以处理最多2 ^ 64字节的内存。

答案 3 :(得分:4)

不考虑内存,数组的最大大小受到用于索引数组的整数类型的限制。

答案 4 :(得分:2)

我猜最大的理论数组是“unsigned long”的最大值(或者是最新标准/编译器支持的最大整数)

答案 5 :(得分:2)

指针的大小将限制您能够访问的内存。即使硬件提供对无限内存的支持,如果您能够使用的最大数据类型是64位,那么您将只能访问2 ^ 64字节的内存。

答案 6 :(得分:0)

我一直在寻找一种方法来确定数组的最大大小。这个问题似乎也有同样的问题,所以我想分享我的发现。

最初,C不提供任何函数来确定编译时数组中可分配的最大元素数。这是因为它将取决于机器中可用的存储器。

另一方面,我发现,内存分配函数(calloc()malloc())可以分配更大的数组。而且,这些函数允许您处理运行时内存分配错误。

希望有所帮助。