C语言基础篇—内存的动态分配

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_43313035/article/details/83828470

一、从一个字符串中删除另一个字符串中出现的字符

char *DeleteChars(char *str1,char *str2)
{
 assert(str1 != NULL && str2 != NULL);
 //1、遍历str2,标志
 bool hashTable[256] = {false};
 while(*str2 != '\0')//come
 {
  hashTable[*str2] = true;
  str2++;
 }
 //遍历str1  welcome tulun
 char *pf = str1;
 char *ps = str1;
 while(*pf != '\0')
 {
  if(!hashTable[*pf])
  {
   *ps++ = *pf;
  }
  pf++;
 }
 *ps = '\0';
 return str1;
}

二、判断今年中的第几天

int Today(Day * pdays)
{
 int today = 0;
 int arr[] = {31,28,31,30,31,30,31,31,30,31,30,31};
 if((pdays->year % 4 == 0 && pdays->year %100 != 0)
  || pdays->year % 400 == 0)
 {
  arr[1] = 29;
 }
switch(pdays->month) 
 {
 case 12://12
  today += arr[10];
 case 11://
  today += arr[9];
 case 10://
  today += arr[8];
 case 9://
  today += arr[7];
 case 8://
  today += arr[6];
 case 7://
  today += arr[5];
 case 6://
  today += arr[4];
 case 5://
  today += arr[3];
 case 4://
  today += arr[2];
 case 3://
  today += arr[1];
 case 2://
  today += arr[0];
 case 1:
  today += 0;
  break;
 }
 today += pdays->day;
 return today;
}

三、用联合体判断大小端

bool IsLittle() 
{
 union MyUnion
 {
  short a;
  char ch;
 }uu;
 uu.a = 0x1234;
   if(uu.ch == 0x34)
 {
  return true;
 }
 return false;
}

四、筛选法求100以内的素数。

void Prime(int n)//0---n
{
 int *p = (int *)malloc(n*sizeof(int));
 assert(p != NULL);
 for(int i = 0;i < n;i++)
 {
  p[i] = 1;//
 }
 for(int i=2;i<=10;i++)
 {
  for(int j=i+i;j<=n;j+=i)//将每一个数的倍数(>=2)置为零
  {
   p[j]=0;
  }
 }
 for(int k = 2;k < n;k++)
 {
  if(p[k] == 1)
  {
   printf("%d ",k);
  }
 }
 printf("\n");
}

五、
(1)用malloc在堆上申请一块连续的内存(2G或2.9G这是由于Linux不同的内核版本造成的),malloc申请的那块内存区域的值为随机值
(2)free()释放内存,有几种情况会发生崩溃??

  • p移动了(p++;free(p);)
  • 重复释放同一块内存
  • 释放的不是动态内存开辟的空间(int a=10;int *p=&a;free(p);)
  • 越界int *p=(int *)malloc(5*sizeof(int)); for(int i=0;i<=5;i++) { p[i]=0; }
    (3)calloc 申请增加内存空间(默认值为0
    int *p=(int *)calloc(5,sizeof(int))//申请增加20个字节的存储空间

(4)realloc()
给一个已将分配了地址的指针重新分配空间,参数p为原有的空间地址,后边的参数是重新申请的地址空间大小。
realloc容易引起的bug:
(1)

void *ptr = realloc(ptr, new_size);
if (!ptr) 
{    // 错误处理
}

这里就引出了一个内存泄露的问题,当realloc() 分配失败的时候,会返回NULL。但是参数中的 ptr 的内存是没有被释放的。如果直接将realloc()的返回值赋给ptr。那么当申请内存失败时,就会造成ptr原来指向的内存丢失,造成内存游离和泄露。

正确处理应该是下面这样

void *new_ptr = realloc(ptr, new_size);
if (!new_ptr) 
{    // 错误处理。
}
ptr = new_ptr;

(2)实际上,malloc(0)是合法的语句,会返还一个合法的指针,且该指针可以通过free去释放。这就造成了很多人对realloc()的错误理解,认为当size为0时,实际上realloc()也会返回一个合法的指针,后面依然需要使用free去释放该内存。

void *new_ptr = realloc(old_ptr, new_size);
//其它代码
free(new_ptr);

由于错误的认识,不去检验new_size是否为0,还是按照new_size不为0的逻辑处理,最后并free(new_ptr)。这里就引入了double free的问题,造成程序崩溃。
realloc使用注意事项:

1. realloc失败的时候,返回NULL
2. realloc失败的时候,原来的内存不改变,也就是不free或不move,(这个地方很容易出错)
3. 假如原来的内存后面还有足够多剩余内存的话,realloc的内存=原来的内存+剩余内存,realloc还是返回原来内存的地址; 假如原来的内存后面没有足够多剩余内存的话,realloc将申请新的内存,然后把原来的内存数据拷贝到新内存里,原来的内存将被free掉,realloc返回新内存的地址
4. 如果size为0,效果等同于free()
5. 传递给realloc的指针必须是先前通过malloc(), calloc(), 或realloc()分配的  
6. 故p = (int *) realloc (p, sizeof(int) *15);
7. 语句有这么一个问题,调用前p指向一个已分配成功的内存,而调用realloc时却失败(即返回NULL),此时,p原来指向的内存还没有free掉,而现在又找不到地址,这样就出现memory leak了。
8.针对第六种情况,可以这样来解决:
int *q
q = (int *) realloc (p, sizeof(int) *15);
if(!q) p =q;










展开阅读全文

没有更多推荐了,返回首页