我在C99中找到了有关可变长度数组的信息,但看起来它的行为几乎与malloc + free相同。
我发现的实际差异:
unsigned size = 4000000000;
int* ptr = malloc(size); // ptr is 0, program doesn't crash
int array[size]; // segmentation fault, program crashes
int* ptr = malloc(size);
...
if(...)
return;
...
free(ptr);
我的问题是:
最佳答案
一些实用建议:
实际上,
malloc()
及其 friend 则在堆上分配,这很可能会允许更大的分配。此外,您对该进程有更多控制权,因为malloc()
如果失败,可能会返回NULL
。换句话说,您必须小心使用VLA,不要在runtine中炸毁堆栈。 __STDC_NO_VLA__
宏时不支持它们。 根据我的经验(诸如使用试验除法,Miller-Rabin等查找质数的数字程序),我不会说VLA比
malloc()
快得多。当然,调用malloc()
会有一些开销,但是似乎更重要的是数据访问效率。这是一些使用GNU/Linux x86-64和GCC编译器的快速比较。请注意,结果可能因平台,另一个甚至编译器的版本而异。您可以将数据访问
malloc()
与VLA基准测试作为一些基本的(尽管非常完善)。prime-trial-gen.c
:#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;
}
编译并运行:
$ gcc -std=c99 -pedantic -Wall -W prime-trial-gen.c
$ ./a.out
这是第二个程序,它使用生成的“素数字典”:
prime-trial-test.c
:#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版本):
$ 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版本):
$ 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
如您所愿check
π(10**7)
确实是664,579
。请注意,两个执行时间几乎相同。关于c - 什么时候在C中使用可变长度数组,但是何时进行动态分配?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27337168/