什么是堆内存
//一定要掌握
// - 堆内存基本特征:
// - 相比栈内存,堆的总大小仅受限于物理内存,在物理内存允许的范围内,系统对堆内存的申请不做限制。
// - 相比栈内存,堆内存从下往上增长。
// - 堆内存是匿名的,只能由指针来访问。
// - 自定义分配的堆内存,除非开发者主动释放,否则永不释放,直到程序退出。
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char const *argv[])
{
char *p="jack";
char *str=malloc(100);
str=p;
// str[0]='k';
printf("%s",p);
return 0;
}
malloc基本定义与用法
malloc函数是一种分配长度为num_bytes字节的内存块的函数,可以向系统申请分配指定size个字节的内存空间。malloc的全称是memory allocation(动态内存分配),当无法知道内存具体位置的时候,想要绑定真正的内存空间,就需要用到动态的分配内存。返回类型是 void* 类型。void* 表示未确定类型的指针。C,C++规定,void* 类型可以通过类型转换强制转换为任何其它类型的指针。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(int argc, char const *argv[])
{ // 申请堆空间,可以存放100个char类型
char *str=malloc(sizeof(char)*100);
//str="jack";//str指向字符串常量,写法异常
memcpy(str,"jack",5);
str[2]='g';
printf("%s\n",str);
//申请整型堆空间
int a[10]={1,2,3,4,5};
int *int_p=malloc(sizeof(int)*10);
//手动清空malloc
memset(int_p,0,sizeof(int)*10);
int_p[0]=10;//*int_p
int_p[1]=20;//*(int_p+1)
int_p[2]=30;
printf("%d\n",int_p[2]);
memcpy(int_p,a,sizeof(a)/sizeof(a[0]));
printf("%d\n",int_p[1]);
printf("%d\n",int_p[2]);
//释放堆空间
free(int_p);
//释放堆空间后,无法通过in_p访问堆空间
memcpy(int_p,a,sizeof(a)/sizeof(a[0]));//无法访问
printf("%d\n",int_p[1]);
return 0;
}
练习:练习用堆空间完成冒泡排序
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(int argc, char const *argv[])
{
printf("inputdata:");
int a[5]={0};
for(int i=0;i<5;i++)
{
scanf("%d",&a[i]);
}
int len=sizeof(a)/sizeof(a[0]);
int *p=malloc(sizeof(int)*5);
memset(p,0,sizeof(int)*5);
memcpy(p,a,sizeof(a));
for(int i=0;i<len-1;i++)
{
for(int j=0;j<len-1-i;j++)
{
if(p[j]>p[j+1])
{
int temp=0;
temp=p[j];
p[j]=p[j+1];
p[j+1]=temp;
}
}
}
for(int i=0;i<len;i++)
{
printf("%d",p[i]);
}
free(p);
return 0;
}
用malloc开辟二维数组
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(int argc, char const *argv[])
{ // malloc是以字节为单位
// int *ptr=malloc(sizeof(int)*3);
// //数组[]表示数据的个数,总大小是数据个数乘以类型
// for(int i=0;i<3;i++)
// {
// ptr[i]=i;
// }
//将malloc转为二维数组
int **ptr1=(int**)malloc(sizeof(int)*3);//代表三行
int count=0;
for(int i=0;i<3;i++)
{
for(int j=0;j<4;j++)
{
ptr1[i]=(int*)malloc(4*sizeof(int));
ptr1[i][j]=++count;
printf("%d\t",ptr1[i][j]);
}
printf("\n");
}
return 0;
}
求子集
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int **subsets(int *nums, int numSize, int *returnSize, int **returnColnumSize)
{
// 子集个数
int row = 1 << numSize;
// 子序列
int childNums[numSize * sizeof(int)];
*returnSize = row;
*returnColnumSize = calloc(row,sizeof(int));
int col = 0;
memset(childNums,0,numSize * sizeof(int));
// 申请堆空间,存放每个子集的首元素地址
int **allStr = (int **)calloc(row,sizeof(int *));
if(allStr == NULL)
{
perror("calloc failed: ");
return NULL;
}
for(int i = 0; i < row; i++)
{
col = 0;
for(int j = 0; j < numSize; j++)
{
// 对i的每一位尝试构成子集
if(i & (1 << j))
{
// 如果i的第j位的二进制位为真,则nums[j]元素入子集
childNums[col++] = nums[j];
}
}
// 申请空间用于存放子集
int *temp = (int *)calloc(col,sizeof(int));
memcpy(temp, childNums, col*sizeof(int));
// 将temp挂在allStr的某一个元素
allStr[i] = temp;
// 记录每个子集的元素个数
returnColnumSize[0][i] = col;
}
return allStr;
}
int main(int argc, char const *argv[])
{
int nums[] = {1,2,3};
// nums元素的个数
int size = sizeof(nums) / sizeof(nums[0]);
int returnSize;
int *returnColnumSize;
int **allStr = subsets(nums, size, &returnSize, &returnColnumSize);
// 遍历集合
for(int i = 0; i < returnSize; i++) // 遍历allStr
{
for(int j = 0; j < returnColnumSize[i]; j++)
{
printf("%d\t",allStr[i][j]);
}
printf("\n");
}
return 0;
}