#define _CRT_SECURE_NO_WARNINGS//必须放在第一行
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
//#include <vld.h>//必须先安装
/*
* 局部变量:定义在函数内部的变量,包括形参,在栈(stack)中,
作用域在函数内部有效,生存周期:进入函数创建,退出函数销毁
* void :没有,可以修饰返回值或参数列表
* void *:通用指针,仅仅只标记地址,不包含类型信息
* 动态内存:
* 内存区域:堆(heap),很大接近可用内存,内存申请和销毁需要程序自行管理
* malloc:
* calloc:把每个元素初始化为0
* realloc:
* free:释放内存,不释放则内存泄漏
* 泄漏的内存什么情况还给系统:
* 1.程序(进程)退出
* 2.关机(重启)
* 应用场景:
1.需要根据变量作为长度定义数组
2.函数结束后还需要继续使用的内存(例如返回局部数组的地址,链表)
3.长度较大的数组(大内存,超过栈1M的大小)
*/
char* GetStr1()//error
{
char str[] = "hello world";
return str;//0x00200
}
int Getnum()
{
int a = 10;
return a;
}
char* GetStr()
{
int len = strlen("hello world");
//char* str = (char*)malloc(len * sizeof(char));//常见错误
char* str = (char*)malloc((len+1) * sizeof(char));
assert(str != NULL);
strcpy(str,"hello world");
return str;
}
//课堂练习,返回str复制n次,("abc",2)->"abcabc"
char* GetMemory(const char* str, int n)
{
char *p = (char *)malloc(strlen(str)*n +1);
assert(p != NULL);
if (p == NULL)
{
perror("");
return NULL;
}
p[0] = '\0';//把p变成字符串
for (int i = 0; i < n; i++)
strcat(p,str);
return p;
}
//int main()
//{
// int n = 10;
// int *arr = (int *)calloc(n,sizeof(int));
// for (int i = 0; i < n; i++)
// printf("%d ",arr[i]);
// free(arr);
//
// return 0;
//}
int main()//作业
{
int n = 10;
int* arr = (int*)malloc(n * sizeof(int));
assert(arr != NULL);
for (int i = 0; i < n; i++)//模拟arr被使用
arr[i] = i;
//使用的过程中发现内存不足,实际需要20个单元
//1.申请更大的内存
//2.把原数据复制到新内存
//3.释放原内存
//4.更新地址
return 0;
}
//int main()
//{
// int* arr = (int*)malloc(40);
// free(arr);
// return 0;
//}
//int main()
//{
// //定义1000000长度的int数组
// //int arr[1000000];//不能定义这么大的数组
// //int* arr = (int*)malloc(1000000 * sizeof(int));//ok
// //char* arr = (char*)malloc(1024 * 1024 * 1024);//1G,ok
// char* arr = (char*)malloc(1024 * 1024 * 1020*2);//20亿字节,2G失败
// if (arr == NULL)
// perror("出错了");
// assert(arr != NULL);
// printf("好了\n");
// getchar();
// free(arr);
//
// return 0;
//}
//int main()
//{
// char* p = GetMemory("abcde",5);
// printf("%s\n",p);
// free(p);
// return 0;
//}
//int main()
//{
// char* p = GetStr();//0x00200
// printf("%s\n",p);
//
// int n = Getnum();
// printf("%d\n",n);
//
// return 0;
//}
//int main(void)
//{
// int n = 10;
// //int arr[n];//error,变量不能作为数组的长度,C99合法
// int *p = (int *)malloc(n*sizeof(int));//创建成功后,p类似数组名
// assert(p != NULL);
// if (p == NULL)
// {
// perror("出错了");
// return 0;
// }
//
// for (int i = 0; i < n; i++)
// p[i] = i;
// for (int i = 0; i < n; i++)
// printf("%d ",p[i]);
//
// return 0;
//}
//课堂练习
//int main()
//{
// int n;
// scanf("%d",&n);
// //创建n长度的double类型数组
// double* arr = (double*)malloc(n * sizeof(double));
// assert(arr != NULL);
// if (arr == NULL)
// return -1;
// for (int i = 0; i < n; i++)
// arr[i] = i;
// for (int i = 0; i < n; i++)
// printf("%.1f ",arr[i]);
//
// return 0;
//}
#define _CRT_SECURE_NO_WARNINGS//必须放在第一行
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <vld.h>
/*
*动态内存: 一定把它当作数组使用
* 内存区域:堆(heap),很大接近可用内存,内存申请和销毁需要程序自行管理
* malloc:动态申请内存
* calloc:把每个元素初始化为0
* realloc:扩容,数据结构(顺序表,顺序栈,C++中string)
* free:释放内存,不释放则内存泄漏
* free崩溃的原因:
* 1.越界
* 2.移到指针
* 3.重复释放或者释放非动态内存
*
*/
/*
* 1.二进制求和
给你两个二进制字符串 `a` 和 `b` ,以二进制字符串的形式返回它们的和。
例1:输入参数("11","1"),返回"100";例2:输入("1010","1011"),返回"10101"
*/
char* AddBinary(char* str1, char* str2)
{
int len1 = strlen(str1);
int len2 = strlen(str2);
int n = len1 > len2 ? len1 : len2;
char* s = (char*)malloc((n + 1 + 1) * sizeof(char));
assert(s != NULL);
char* p1 = str1 + len1-1;//str1的尾
char* p2 = str2 + len2 - 1;//str2的尾
int i = 0;//s的下标
int tmp = 0;//保存进位
int count;//和
while (p1 >= str1 && p2 >= str2)//p1,p2都还有值
{
count = (*p1 - '0') + (*p2 - '0') + tmp;
s[i++] = count%2 + '0';
tmp = count / 2;
p1--;
p2--;
}
while (p1 >= str1)//只剩p1
{
count = (*p1 - '0') + tmp;
s[i++] = count % 2 + '0';
tmp = count / 2;
p1--;
}
while (p2 >= str2)//只剩p2
{
count = (*p2 - '0') + tmp;
s[i++] = count % 2 + '0';
tmp = count / 2;
p2--;
}
if (tmp > 0)
s[i++] = '1';
s[i] = '\0';
//s逆置
--i;//跳过'\0'
for (int j = 0; j < i; j++, i--)
{
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
return s;
}
/*
* 4.有 n 个整数,使前面各数顺序向后移 m 个位置,
最后 m 个数变成最前面的 m个数,见下图,
写一个函数实现该功能。
*/
void Move(int* arr, int n, int m)
{
if (m < 0 || m >= n)
return;
int* brr = (int*)malloc(m * sizeof(int));
assert(brr != NULL);
//把后面m个数据移到brr
//把arr的前n-m个数据后移m个位置
//把brr的数据复制到arr的前面
free(brr);
}
int main()
{
char str1[] = "0101";
char str2[] = "101";
char *p = AddBinary(str1,str2);
printf("%s\n",p);
free(p);
return 0;
}
/*
//1.越界
int main()
{
int n = 10;
int* arr = (int*)malloc(n );
assert(arr != NULL);
for (int i = 0; i < n; i++)
arr[i] = i;
for (int i = 0; i < n; i++)
printf("%d ",arr[i]);
printf("\n");
free(arr);
return 0;
}
*/
/*
//2.移到指针
int main()
{
int n = 10;
int* arr = (int*)malloc(n*sizeof(int));
assert(arr != NULL);
for (int i = 0; i < n; i++)
{//arr[i] = i;
*arr = i;
arr++;
}
printf("\n");
free(arr);
return 0;
}
*/
/*
//重复释放同一段内存
int main()
{
int n = 10;
int* arr = (int*)malloc(n * sizeof(int));
assert(arr != NULL);
for (int i = 0; i < n; i++)
{
arr[i] = i;
}
printf("%p\n", arr);
free(arr);
printf("%p\n",arr);//arr是野指针
free(NULL);//可以
//free(arr);//崩溃,重复释放
return 0;
}
*/
//int main()
//{
// int n = 10;
// int* arr = (int*)malloc(n * sizeof(int));
// assert(arr != NULL);
// free(arr);
//
// arr = (int*)malloc(2*n * sizeof(int));//arr还能不能继续使用
//
// free(arr);
//
// return 0;
//}
//int main()
//{
// int n = 10;
// int* arr = (int*)malloc(n * sizeof(int));
// assert(arr != NULL);
// printf("%p\n",arr);
// arr = (int*)realloc(arr,n*2*sizeof(int));
// printf("%p\n", arr);
// free(arr);
// return 0;
//}
/*
int main()
{
int n = 10;
int* arr = (int*)malloc(n * sizeof(int));
assert(arr != NULL);
for (int i = 0; i < n; i++)//模拟arr被使用
arr[i] = i;
//使用的过程中发现内存不足,实际需要20个单元
arr = (int *)realloc(arr,2*n*sizeof(int));//等同下面所有语句
1.申请更大的内存
//int* p = (int*)malloc(2 * n * sizeof(int));
//assert(p != NULL);
2.把原数据复制到新内存
//for (int i = 0; i < n; i++)
//{
// p[i] = arr[i];
//}
3.释放原内存
//free(arr);
4.更新地址
//arr = p; p = NULL;
return 0;
}
*/