当使用在C变量长度数组,但是当一个动态分配? [英] When to use variable length array in C, but when a dynamic allocation?

查看:133
本文介绍了当使用在C变量长度数组,但是当一个动态分配?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我了解在C99变长数组,但它看起来像它的行为几乎相同的malloc +免费的。

I find out about Variable Length Array in C99, but it looks like it behave almost the same as malloc + free.

实际的差异,我发现:


  1. 太大阵列处理:

  1. Too big array handling:

unsigned size = 4000000000;
int* ptr = malloc(size); // ptr is 0, program doesn't crash
int array[size]; // segmentation fault, program crashes


  • 内存泄漏:只能在动态数组分配:

  • Memory leaks: only possible in dynamic array allocation:

    int* ptr = malloc(size);
    ...
    if(...)
        return;
    ...
    free(ptr);
    


  • 对象和可能性的生命从函数返回:动态分配的数组的生活,直到内存释放并可以从分配的内存函数返回

  • Life of object and possibility to return from function: dynamically allocated array lives until the memory is frees and can be returned from function which allocated the memory.

    调整:只有指针分配的内存可能调整

    Resizing: resizing possible only with pointers to allocated memory.

    我的问题是:


    • 有什么更多的不同(我感兴趣的是实际的建议)?

    • 什么是更多的问题,程序员可以有数组的长度可变两种方式?

    • 在当前选择VLA但当动态数组分配?

    • 什么是快?VLA或的malloc +免费

    推荐答案

    一些实际的建议:


    • 沃拉斯是在位于空间有限栈上的做法,而的malloc()和它的朋友分配在堆中,这很有可能让更大的分配。 Moreveover你有这个过程更多的控制权,为的malloc()可以返回 NULL 如果失败。换句话说,你必须要小心VLA没有对打击你叠runtine。

    • 并非所有的编译器都支持VLA,例如视觉工作室。此外 C11标志着他们作为可选功能,并允许不支持他们,当 __ __ STDC_NO_VLA 宏定义。

    • VLAs are in practice located on the space-limited stack, while malloc() and its friends allocates on the heap, that is likely to allow bigger allocations. Moreveover you have more control on that process, as malloc() could return NULL if it fails. In other words you have to be careful with VLA not-to-blow your stack in runtine.
    • Not all compilers support VLA, e.g. Visual Studio. Moreover C11 marked them as optional feature and allows not to support them when __STDC_NO_VLA__ macro is defined.

    从我的经验(数字节目像审判庭,米勒罗宾等发现的素数)我不会说沃拉斯任何速度比的malloc() 。当然还有的malloc()调用的一些开销,但似乎是更重要的是数据访问效率。

    From my experience (numerical programs like finding prime numbers with trial division, Miller-Rabin etc.) I wouldn't say that VLAs are any faster than malloc(). There is some overhead of malloc() call of course, but what seems to be more important is data access efficiency.

    下面是一些快速和放大器;比较脏使用的GNU / Linux的x86-64和GCC编译器。请注意,结果可能会有所不同,从平台到另一个平台,甚至编译器的版本。你可能使用一些基本的数据访问的malloc(虽然很远被完整)() VS VLA基准。

    Here is some quick & dirty comparison using GNU/Linux x86-64 and GCC compiler. Note that results may vary from platform to another or even compiler's version. You might use as some basic (though very far of being complete) data-access malloc() vs VLA benchmark.

    #include <assert.h>
    #include <stdbool.h>
    #include <stdio.h>
    
    bool isprime(int n);
    
    int main(void)
    {
        FILE *fp = fopen("primes.txt", "w");
        assert(fp);
    
        fprintf(fp, "%d\n", 2);
        for (int i = 3; i < 10000; i += 2)
            if (isprime(i))
                fprintf(fp, "%d\n", i);
        fclose(fp);
        return 0;
    }
    
    bool isprime(int n)
    {
        if (n % 2 == 0)
            return false;
        for (int i = 3; i * i <= n; i += 2)
            if (n % i == 0)
                return false;
        return true;
    }
    

    &编译放大器;运行:

    Compile & run:

    $ gcc -std=c99 -pedantic -Wall -W prime-trial-gen.c
    $ ./a.out
    

    然后这里是第二种方案,即采取利用生成的素数大辞典:

    Then here is second program, that take use of generated "primes dictionary":

    #include <assert.h>
    #include <stdbool.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    bool isprime(int n, int pre_prime[], int num_pre_primes);
    int get_num_lines(FILE *fp);
    
    int main(void)
    {
        FILE *fp = fopen("primes.txt", "r");
        assert(fp);
    
        int num_lines = get_num_lines(fp);
        rewind(fp);
    
    #if WANT_VLA
        int pre_prime[num_lines];
    #else
        int *pre_prime = malloc(num_lines * sizeof *pre_prime);
        assert(pre_prime);
    #endif
    
        for (int i = 0; i < num_lines; i++)
            assert(fscanf(fp, "%d", pre_prime + i));
        fclose(fp);
    
        /* NOTE: primes.txt holds primes <= 10 000 (10**4), thus we are safe upto 10**8 */
        int num_primes = 1; // 2
        for (int i = 3; i < 10 * 1000 * 1000; i += 2)
            if (isprime(i, pre_prime, num_lines))
                ++num_primes;
        printf("pi(10 000 000) = %d\n", num_primes);
    
    #if !WANT_VLA
        free(pre_prime);
    #endif
        return 0;
    }
    
    bool isprime(int n, int pre_prime[], int num_pre_primes)
    {
        for (int i = 0; i < num_pre_primes && pre_prime[i] * pre_prime[i] <= n; ++i)
            if (n % pre_prime[i] == 0)
                return false;
        return true;
    }
    
    int get_num_lines(FILE *fp)
    {
        int ch, c = 0;
    
        while ((ch = fgetc(fp)) != EOF)
            if (ch == '\n')
                ++c;
        return c;
    }
    

    &编译放大器;运行(malloc的版本):

    Compile & run (malloc version):

    $ gcc -O2 -std=c99 -pedantic -Wall -W prime-trial-test.c
    $ time ./a.out
    pi(10 000 000) = 664579
    
    real    0m1.930s
    user    0m1.903s
    sys 0m0.013s
    

    &编译放大器;运行(VLA版):

    Compile & run (VLA version):

    $ gcc -DWANT_VLA=1 -O2 -std=c99 -pedantic -Wall -W prime-trial-test.c
    ime ./a.out 
    pi(10 000 000) = 664579
    
    real    0m1.929s
    user    0m1.907s
    sys 0m0.007s
    

    你可能检查 π(10 ** 7 )确实 664579 。注意,两个执行时间几乎是相同的。

    As you might check π(10**7) is indeed 664,579. Notice that both execution times are almost the same.

    这篇关于当使用在C变量长度数组,但是当一个动态分配?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆