动态分配内存函数malloc(),calloc(),realloc()

输出给定范围内的所有质数

#define __STDC_WANT_LIB_EXT1__ 1
#include 
#include 
#include 
#define CAP_INCR 10

int main(){
	unsigned long long* pPrimes = NULL;
	bool found = false;
	unsigned long long limit = 0LL;
	int count = 0;

	printf("Enter the limit for primes you want to find: ");
	scanf_s("%llu", &limit);          //可以有第三个参数来指定读取的字节数,从而避免读取不必要的数据导致更改了其他变量的值

	size_t capacity = 10;
	pPrimes = calloc(capacity, sizeof(unsigned long long));
	if(!pPrimes){
		printf("Not enough memory.\n");
		return 1;
    }
	*pPrimes = 2ULL;
	*(pPrimes + 1) = 3ULL;
	*(pPrimes + 2) = 5ULL;
    count = 3;

	unsigned long long trial = *(pPrimes + 2) + 2ULL;
	unsigned long long* pTemp = NULL;
	while(trial <= limit){
	    for(int i = 1 ; i < count ; ++i){
		    if(!(found = (trial % *(pPrimes + i))))    //一个奇数不能被它之前的所有质数整除,它就是质数
			    break;
		}
		if(found){                                 //根据是否是质数来判定要不要存储它
			if(count == capacity){                 //个数到达分配内存的极限就开始扩展内存分配
                capacity += CAP_INCR;
				pTemp = realloc(pPrimes, capacity*sizeof(unsigned long long));    //realloc()函数的关键点,会释放旧内存
				if(!pTemp){
					printf("Not enough memory.\n");
					free(pPrimes);
					pPrimes = NULL;
					return 2;
				}
				pPrimes = pTemp;          //不直接将realloc()函数返回给pPrimes是不希望函数返回失败时返回pPrimes一个NULL
			}
			*(pPrimes + count++) = trial;
		}
		trial += 2ULL;
	}
	printf("%d primes found:\n");
	for(int i = 0 ; i < count ; ++i){
	    printf("%12llu", *(pPrimes + i));
		if(!((i + 1) % 5))
			printf("\n");
	}
	printf("\n");
	free(pPrimes);         //只要释放pTemp分配的内存即可
	pPrimes = NULL;
	return 0;
}


动态分配内存优点是需要多大的内存可以自己控制,不需要时释放,但同时也带来了许多管理上的问题。
使用时的基本原则:
1,避免分配大量小的内存块,每次分配内存都会增加系统开销。
2,仅在需要时分配,使用完后就释放它。
3,释放之前确保没有覆盖已分配内存的地址,如果将分配的内存地址设为NULL,这块分配的内存就找不到了,就会发生内存泄漏。在循环分配内存时要特别小心。

你可能感兴趣的:(C语言入门经典)