4. 指针和动态内存
一、栈vs堆
stack、static/global、Code在编译期大小就确定了。只有堆区(动态分配内存),它不是固定的
🍐栈溢出:无穷递归的情况
- 内存中预留给栈的空间,在运行期间不会增长。
- 堆是一块很大,可以自由使用的内存
🍊 堆主要涉及的function
🍋 例子
- 在堆上分配的内存需要手动释放
二、malloc calloc realloc free
🍌 malloc
不能对void* 直接进行操作,为了使用这块内存,需要对指针进行类型转换
🍉 calloc
- 与 malloc 不同,有两个传输参数,第一个参数是特定类型的元素数量,第二个参数是类型的大小
- malloc分配完内存之后并不会对其进行初始化,calloc会将其初始化为0
🍇 relloc
- 如果有一块动态分配的内存,然后你想修改内存的大小
- 第一个参数是指向已经分配内存的起始地址的指针,第二个参数是新的内存块的大小
🍓 free
🍈例子
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
printf("请输入数组大小\n");
scanf("%d",&n);
int *A = (int*)calloc(n,sizeof(int));
int *B = (int*)malloc(n*sizeof(int)); //实测也初始化后居然是0
for(int i=0;i<n;i++)
printf("%d ",A[i]);
printf("\n");
for(int i=0;i<n;i++)
printf("%d ",B[i]);
printf("\n");
free(A);
free(B);
A[2] = 8; // 我的开发环境free后仍可以修改
printf("after free\n");
for(int i=0;i<n;i++)
printf("%d ",A[i]);
printf("\n");
for(int i=0;i<n;i++)
printf("%d ",B[i]);
printf("\n");
int *c = (int*)malloc(n*sizeof(int));
int *d = (int*)realloc(c,2*n*sizeof(int));
printf("旧地址:%d ,新地址:%d \n",c,d);
}
输出
请输入数组大小
10
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
after free
0 0 8 21845 0 0 0 0 0 0
1433758336 21845 1433755664 21845 0 0 0 0 0 0
旧地址:1433758384 ,新地址:1433758384
三、内存泄漏
/*
简单的赌博游戏
JQK电脑自动洗牌
玩家猜测Q的位置 1 2 3
猜对了:收获3倍下注金额
猜错了:失去下注金额
开局有100块
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int cash = 100;
void play(int bet)
{
//char c[3] = {'J','Q','K'}; // 正常写法,不会有内存泄露【因为栈自动“free”】
char *c = (char*)malloc(1024*1024*sizeof(char));
c[0] = 'J'; c[1] = 'Q'; c[2] = 'K';
printf("洗牌中\n");
srand(time(NULL)); // 随机数种子
int i;
for(i=0;i<5;i++)
{
int x = rand()%3;
int y = rand()%3;
int temp = c[x];
c[x] = c[y];
c[y] = temp; // 调换xy位置
}
int playersGuess;
printf("Q 在哪个位置 1,2,3?\n");
scanf("%d",&playersGuess);
if(c[playersGuess-1] == 'Q')
{
cash += 3*bet;
printf("你赢了,结果是 \"%c %c %c\" 总金额 = %d\n",c[0],c[1],c[2],cash);
}
else
{
cash -= bet;
printf("你输了,结果是 \"%c %c %c\" 总金额 = %d\n",c[0],c[1],c[2],cash);
}
//free(c);
}
int main()
{
int bet;
printf("总金额 = %d\n",cash);
while(cash>0)
{
printf("请输入下注金额");
scanf("%d",&bet);
if(bet==0||bet>cash) break;
play(bet);
printf("\n*************************\n");
}
}