84669 人学习
152542 人学习
20005 人学习
5487 人学习
7821 人学习
359900 人学习
3350 人学习
180660 人学习
48569 人学习
18603 人学习
40936 人学习
1549 人学习
1183 人学习
32909 人学习
认证高级PHP讲师
经过了好长时间,我才勉强总结了一个答案。
首先,如果要确定一个数组的最大长度,我们需要知道它的数据类型,因此,数组的数据类型是其中一个限制因素。因为不同数据类型的元素大小不同。很显然(我们假设int为4字节,char为1字节),数据类型为char的数组的最大长度是类型为int的数组的4倍。
int
char
另外,我们不难想到,大小(size)的数据类型,也就是数组下标的数据类型,其实也是一个限制因素。在C/C++中,数组下标的类型是std::size_t,因此数组的大小首先不能超过size_t所能表示的大小。这个数据类型是在库文件stdio.h中通过typedef声明的,对于32位程序它被定义为unsighed int,对于64位程序定义为unsigned long。前者能表示的最大大小为2^32-1,后者为2^64-1。
std::size_t
size_t
stdio.h
typedef
unsighed int
unsigned long
然后,我又想到了物理内存的大小。这一点不用细说,因为程序运行时一旦超过物理内存的大小,这个程序就会立刻崩溃。
上面几点都是比较笼统的限制,我们换一个高大上的表达——宏观上的限制因素。下面,我们介绍几个微观上的限制因素。
大家应该都知道,数组的分配方式大概有两种方式:静态分配和动态分配。再具体点儿的话,根据数组声明的位置,我们可以将数组分为局部数组和全局数组。这样讨论的话,就复杂了,我们暂时可以将数组分为四类(只是笔者本人这样划分,不知道官方是否有这样的分类):静态分配的局部数组、动态分配的局部数组、静态分配的全局数组、动态分配的全局数组。
第一种数组分配时,使用的是栈上的空间,因此静态分配得到的局部数组的大小受限于栈的大小。具体来说是数组所在函数栈帧的大小,当然栈帧的大小肯定不能超过栈的大小。如果你对编译器的使用比较熟悉或者你阅读过编译器文档的话,你应该知道如何调整栈帧的大小限制。在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将会提示溢出。
对于第二种数组和第四种数组,我觉得应该划分为一类。本质上它们都是在堆上分配空间,因此它们的大小受限于堆的大小。堆是不连续的内存区域,堆的大小受限于计算机系统中有效的虚拟内存,因此堆的大小一般都比较大。
至于第三种数组,我们知道它是在静态存储区分配内存空间,因此大小自然受限于静态存储区的大小,也叫做BSS(Block Started by Symbol),在汇编语言中,我么也称之为数据段。目前我还不太清楚静态存储区的大小限制,我在我的电脑(Core i3-3110M, 内存8GB)上做过实验发现我所能分配的最大大小大约为剩余内存的1/2。网上有这样说的:“你的常量有多大就多大”,但是还有待考证。
Note:关于栈帧的概念可以参考《深入理解计算机系统》这本书,或者其他关于计算机体系结构的资料。
已经整理成博客:C++中数组的最大长度。
如果是栈上的数组,大小受限于堆栈大小(记得是4MB)。如果是堆的话,就比较大了,理论上可以使用操作系统允许进程使用的最大内存,减去内存中的代码、常量等占用的空间。不过非要全部用上,那么程序离崩溃也就不远了。
和 cpu 的寻址位宽相关,以及和 操作系统 的寻址模式相关
在虚拟内存的平坦寻址模式下
32位的指针寻址范围是 2^32 = 4GB
数组可以分别开在堆、栈、静态存储区,看你的需要、CPU的支持程度和操作系统的制约。
经过了好长时间,我才勉强总结了一个答案。
首先,如果要确定一个数组的最大长度,我们需要知道它的数据类型,因此,数组的数据类型是其中一个限制因素。因为不同数据类型的元素大小不同。很显然(我们假设
int
为4字节,char
为1字节),数据类型为char
的数组的最大长度是类型为int
的数组的4倍。另外,我们不难想到,大小(size)的数据类型,也就是数组下标的数据类型,其实也是一个限制因素。在C/C++中,数组下标的类型是
std::size_t
,因此数组的大小首先不能超过size_t
所能表示的大小。这个数据类型是在库文件stdio.h
中通过typedef
声明的,对于32位程序它被定义为unsighed int
,对于64位程序定义为unsigned long
。前者能表示的最大大小为2^32-1,后者为2^64-1。然后,我又想到了物理内存的大小。这一点不用细说,因为程序运行时一旦超过物理内存的大小,这个程序就会立刻崩溃。
上面几点都是比较笼统的限制,我们换一个高大上的表达——宏观上的限制因素。下面,我们介绍几个微观上的限制因素。
大家应该都知道,数组的分配方式大概有两种方式:静态分配和动态分配。再具体点儿的话,根据数组声明的位置,我们可以将数组分为局部数组和全局数组。这样讨论的话,就复杂了,我们暂时可以将数组分为四类(只是笔者本人这样划分,不知道官方是否有这样的分类):静态分配的局部数组、动态分配的局部数组、静态分配的全局数组、动态分配的全局数组。
第一种数组分配时,使用的是栈上的空间,因此静态分配得到的局部数组的大小受限于栈的大小。具体来说是数组所在函数栈帧的大小,当然栈帧的大小肯定不能超过栈的大小。如果你对编译器的使用比较熟悉或者你阅读过编译器文档的话,你应该知道如何调整栈帧的大小限制。在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将会提示溢出。
对于第二种数组和第四种数组,我觉得应该划分为一类。本质上它们都是在堆上分配空间,因此它们的大小受限于堆的大小。堆是不连续的内存区域,堆的大小受限于计算机系统中有效的虚拟内存,因此堆的大小一般都比较大。
至于第三种数组,我们知道它是在静态存储区分配内存空间,因此大小自然受限于静态存储区的大小,也叫做BSS(Block Started by Symbol),在汇编语言中,我么也称之为数据段。目前我还不太清楚静态存储区的大小限制,我在我的电脑(Core i3-3110M, 内存8GB)上做过实验发现我所能分配的最大大小大约为剩余内存的1/2。网上有这样说的:“你的常量有多大就多大”,但是还有待考证。
Note:关于栈帧的概念可以参考《深入理解计算机系统》这本书,或者其他关于计算机体系结构的资料。
已经整理成博客:C++中数组的最大长度。
如果是栈上的数组,大小受限于堆栈大小(记得是4MB)。如果是堆的话,就比较大了,理论上可以使用操作系统允许进程使用的最大内存,减去内存中的代码、常量等占用的空间。不过非要全部用上,那么程序离崩溃也就不远了。
和 cpu 的寻址位宽相关,以及和 操作系统 的寻址模式相关
在虚拟内存的平坦寻址模式下
32位的指针寻址范围是 2^32 = 4GB
数组可以分别开在堆、栈、静态存储区,看你的需要、CPU的支持程度和操作系统的制约。