C中的数组大小是否有限制?

时间:2017-09-03 23:45:15

标签: c arrays

首先,here is my code只是为了让您能够跟上。

#include <stdio.h>
#include <stdlib.h>

#define MAX 10000000

long long min(long long a, long long b, long long c) {

    long long temp_min = a;
    if (b < temp_min) temp_min = b;
    if (c < temp_min) temp_min = c;

    return temp_min;

}

long long numOp (long long n, long long memo[]) {

    memo[1] = 0;

    for (int i = 2; i <= n; i++) {

        long long guess_1 = MAX, guess_2 = MAX, guess_3 = MAX;

        guess_1 = memo[i - 1] + 1;

        if (i % 2 == 0) guess_2 = memo[i / 2] + 1;

        if (i % 3 == 0) guess_3 = memo[i / 3] + 1;

        memo[i] = min(guess_1, guess_2, guess_3);

    }

    return memo[n];

}

int main (void) {
    // Read the input from the user
    long long n, v = 0, N;
    scanf ("%lld", &n);
    N = n;

    long long num_operations[n + 1];
    long long sequence[n];

    for (long long i = 1; i <= n; i++) {
        num_operations[i] = -1;
    }

    for (long long l = 0; l < n; l++) {
        sequence[l] = -1;
    }

    // Compute the minimum number of operations required to get to n starting form 1
    long long op = numOp (n, num_operations);

    // Print the result
    printf ("%lld\n", op);

    sequence[v++] = n;
    while (n > 1) {

        if (num_operations[n - 1] < num_operations[n]) {

            //printf("%lld ", n - 1);
            sequence[v++] = n - 1;
            n = n - 1;

        } else {

            long long temp1 = -1, 
                      temp2 = -1;

            if (n % 2 == 0) {
                temp1 = num_operations[n / 2];
            } 

            if (n % 3 == 0) {
                temp2 = num_operations[n / 3];
            }

            if (temp2 < temp1) {

                //printf("%lld ", n / 2);
                sequence[v++] = n / 2;
                n = n / 2;

            } else {

                //printf("%lld ", n / 3);
                sequence[v++] = n / 3;
                n = n / 3;

            }
        }
    }

    // Print the intermediate numbers from 1 up through n
    for (long long k = N - 1; k >= 0; k--) {
        if (sequence[k] != -1)
            printf("%lld ", sequence[k]);
    }
    printf("\n");

    return 0;
}

所以我正在研究这个输入n的问题,使得n在1到1,000,000之间。该程序适用于高达100,000的输入,但一旦达到(甚至低于)1,000,000,我就会遇到分段错误。

我调试了程序以缩小可能性并发现分段错误发生在第52行,我尝试访问数组元素。

我唯一的猜测是,对于C中的数组有多大可以获得某种限制,如果是这样的话,你们有什么方法可以解决它吗?

2 个答案:

答案 0 :(得分:1)

当然,因为索引不能大于SIZE_MAX。但是,在堆栈中分配自动变量时,这不是问题。堆栈的大小非常有限。您可以使用malloc函数系列在堆上分配更多内容。当然,您受程序堆可用的限制

答案 1 :(得分:1)

您使用VLA作为call stack分配的自动变量。因此,您受限于调用堆栈的最大大小(通常只有几兆字节,详细信息是操作系统和计算机特定的)。

您应该在堆上分配这些。阅读C dynamic memory allocation。所以代码改为

long long *num_operations = calloc (n + 1, sizeof(long long));
long long *sequence = calloc(n, sizeof(long long));

不要忘记测试calloc的失败:

if (!num_operations) 
    { perror("num_operations calloc"); exit(EXIT_FAILURE); }

同样适用于calloc

sequence

不要忘记free(例如,在main结束时)

free (num_operations);
free (sequence);

避免memory leaks(使用valgrind调试这些)。在您的特定情况下,您可能不会free,因为当virtual address space结束时,程序的process(在Linux或Windows上等等)被删除。

仅供参考malloccallocfree正在使用system calls(例如mmap(2))来更改虚拟地址空间。但通常C标准库不会向操作系统发布(使用munmapfree - d内存,但会将其标记为未来malloc - s或{{1}可重用} -s

在实践中,一旦它变得不必要,你就会有更好的calloc记忆(所以你经常可以在同一个例程中freecalloc。阅读garbage collection技术,概念和术语是值得的。

当然,堆分配的内存也是有限的(因为您的计算机资源有限),但限制可能取决于计算机,并且通常要大得多(笔记本电脑至少为千兆字节,超级计算机可能为太字节);即使资源耗尽,有时free似乎也可以工作(阅读memory overcommitment)(这是我通常禁用的操作系统功能)。在POSIX和Linux系统上setrlimit(2)可以用来降低(或改变一下)这个限制。