【问题标题】:Maximum size array program in C?C中的最大大小数组程序?
【发布时间】:2013-11-25 10:57:18
【问题描述】:

使用以下代码,我试图创建一个数字数组,然后对它们进行排序。但是如果我设置了一个高数组大小(MAX),程序会在最后一个“随机”生成的数字处停止,并且根本不会继续进行排序。谁能帮我解决这个问题?

#include <stdio.h>

#define MAX 2000000

int a[MAX];
int rand_seed=10;

/* from K&R
   - returns random number between 0 and 62000.*/
int rand();
int bubble_sort();

int main()
{
    int i;

    /* fill array */
    for (i=0; i < MAX; i++)
    {
        a[i]=rand();
        printf(">%d= %d\n", i, a[i]);
    }

    bubble_sort();

/* print sorted array */
printf("--------------------\n");
for (i=0; i < MAX; i++)
printf("%d\n",a[i]);

    return 0;
}

int rand()
{
    rand_seed = rand_seed * 1103515245 +12345;
    return (unsigned int)(rand_seed / 65536) % 62000;
}

int bubble_sort(void)
{
    int t, x, y;
    /* bubble sort the array */
    for (x=0; x < MAX-1; x++)
        for (y=0; y < MAX-x-1; y++)
            if (a[y] > a[y+1])
            {
                t=a[y];
                a[y]=a[y+1];
                a[y+1]=t;
            }
     return 0;
}

【问题讨论】:

  • 使用动态数组怎么样?
  • 如果您会阅读(繁体)中文,this 可能会对您有所帮助。
  • 你需要bubble_sort()的返回类型??
  • 由于您的数组是在文件范围内声明的,因此这很可能不是您的问题。可能不是一个好主意是使用 rand() 的熟版本,而不仅仅是库函数。此外,前向声明的语法在现代 C 中更加具体。将(void) 用于不接收参数的函数。

标签: c


【解决方案1】:

问题是您将数组存储在全局部分中,C不保证它可以支持的全局部分的最大大小,这是OS,arch编译器的功能。
所以不是创建一个全局数组,而是创建一个全局 C 指针,使用 malloc 分配一个大块。现在内存被保存在更大的堆中,并且可以在运行时增长。

【讨论】:

  • C 没有说明什么必须存储在堆栈上,什么必须存储在堆上。但总体而言,您的答案是一个不错的答案。
  • @Artur U 是对的...我在一小时前在一台普通机器上运行了该代码,它仍在运行:D .... 是的,该数组不是可执行文件的一部分而我的可执行文件只有 8.5k...
  • @Deepthought:删除了我的评论并做出了回答。
【解决方案2】:

对于静态变量,您的数组将位于 BSS section。它不会是图像的一部分,但程序加载器会在您的程序开始“真正”执行之前分配所需的空间并用零填充它。如果使用嵌入式编译器,你甚至可以控制这个过程,并用你喜欢的任何东西填充你的静态数据。该数组可能占用 2GB 或您的 RAM,而您的 exe 文件可能只有几千字节。我刚刚设法以这种方式使用了超过 2GB 的数组,而我的 exe 为 34KB。我可以相信,当您接近 231-1 个元素(如果您的 int 是 32 位)时,编译器可能会警告您,但现在具有 2m 个元素的静态数组不是问题(除非它是嵌入式系统,但我打赌不是)。

问题可能是您的冒泡排序有 2 个嵌套循环(与所有冒泡排序一样),因此尝试对这个数组进行排序 - 有 2m 个元素 - 会导致程序循环 2*1012 次 (arithmetic sequence):

内循环:

1:1999999次

2: 1999998 次

...

2000000: 1 次

所以你必须交换元素

2000000 * (1999999+1) / 2 = (4 / 2) * 10000002 = 2*1012

(以上如有错误请指正)

您的程序在排序例程中停留的时间太长,而您甚至没有意识到这一点。你看到的只是最后打印的兰特号码并且程序没有响应。即使在我非常快的具有 200K 阵列的 PC 上,以这种方式排序也需要大约 1 分钟。

它与您的操作系统、编译器、堆等无关。您的程序只是在循环执行时卡住了2*1012如果你有 2m 个元素,则次数。

为了验证我的话,在排序之前打印“排序开始”,然后再打印“排序完成”。我敢打赌你会看到的最后一件事是“排序开始”。此外,您可以在 bubble_sort 中的内部循环之前打印当前 x 值 - 您会看到它正在工作。

【讨论】:

  • 感谢您的回答。但是,我仍然添加了: printf("bubble start");就在bubble_sort()之前,但通知永远不会出现在终端上。
  • @user3031004:不敢相信——你有什么 CPU、RAM、操作系统、编译器?而不是调用 rand - 尝试使用任何值初始化您的数组。它会开始排序吗?
【解决方案3】:

动态数组

int *Array;
Array= malloc (sizeof(int) * Size);

【讨论】:

  • malloc 不会“将数组放在堆上” malloc 只是返回一个指向请求数据区域的指针,但它的编译器决定存储位置。
  • @Zaibis 我不认为这是一个非常准确的反对意见。手册页指出“通常,malloc() 从堆中分配内存,并根据需要调整堆的大小,例如使用 sbrk(2)”。只要malloc() 被调用,编译器就不能做任何特别的事情;它只是一个(库)函数。
  • @Zaibis 那么,this 不正确?
  • @unwind 这不是我说的吗?好吧,我指的是 C 标准,其中没有说明内存必须存储在哪里。因此系统可以随意选择何时将数据存储在何处。还是我错了?
  • @KVD 好吧,使用malloc()的解决方案是正确的,但我们的描述在我看来是不正确的。
【解决方案4】:

最初的 C 标准 (ANSI 1989/ISO 1990) 要求编译器成功翻译至少一个包含一组环境限制的至少一个示例的程序。其中一个限制是能够创建至少 32,767 字节的对象。

在 1999 年的 C 标准更新中,这个最小限制被提高到至少 65,535 字节。

提供大于该大小的对象不需要 C 实现,这意味着它们不需要允许大于该大小的整数数组

(int)(65535 / sizeof(int)).

用非常实用的术语来说,在现代计算机上,不可能提前说可以创建多大的数组。它可能取决于计算机中安装的物理内存量、操作系统提供的虚拟内存量、已运行的其他任务、驱动程序和程序的数量以及正在使用的内存量等因素。因此,您的程序今天运行的内存可能比昨天使用的内存更多或更少,或者明天可以使用。

许多平台对自动对象设置了最严格的限制,即那些在函数内部定义而不使用“静态”关键字的对象。在某些平台上,如果它们是静态的或通过动态分配,您可以创建更大的数组。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-02
    • 2015-02-13
    • 2010-12-22
    • 2021-10-07
    • 1970-01-01
    • 2021-03-22
    • 2013-10-28
    相关资源
    最近更新 更多