#include <stdio.h>
#include <stdlib.h>
// puts("hello world!");
// char * str = "100";
// int a;
// sscanf(str, "%d", &a);
// printf("int value is %d\n", a);
//把字符串转化成double
// double value = atof("3.14");
// printf("%f\n", value);
//
// // 把int类型转化成字符串
// int values = 1000;
// char buf[10];
// sprintf(buf, "%d", value);
// puts(buf);
// 动态内存分配
// 为什么要用动态内存
// 静态内存分配,分配内存大小是固定的,静态分配内存会出现以下问题
// 1. 很容易超出栈内存最大值 2. 为了防止内存不够用会开辟更多的内存
// 动态内存分配, 在程序运行过程中,动态指定需要使用的内存大小,手动释放
// 释放之后的这些内存,还可以供其他程序使用或者重用。
// 40M
// stack overflow 错误,栈溢出
// 在栈区中直接分配40M内存,正常来说window下面,\
//一个应用程序分配的栈内存大小在2M,所以这样申请会报stack overflow
// int a[1024*1024*10];
// C语言的内存分配
// 1. 栈区(stack) 自动分配,自动释放,一般是局部变量,用完马上释放了
// 2. 堆区(Heap) 程序员手动分配和释放, 可以分配大概操作熊的80%左右的内存
// 3. 全局区和静态区
// 4. 字符常量区
// 5. 程序代码区
// 在堆内存上分配了一个400的内存
// malloc 返回的是void* 代表他可以返回任意类型的指针,所以这里
// int *p = mallloc(1024*1024*100*sizeof(int));
// getchar();
// free(p); //释放该内存
int main(void) {
// 数组扩容
// 静态内存分配,数组的大小是固定的
int len;
printf("第一次输入数组的长度");
scanf("%d", &len);
int *p= malloc(len*sizeof(int));
//int* p = calloc(len, sizeof(int)); // 自动计算分配的内存大小
//赋值
int i = 0;
//p是内存地址第一个int 4字节的地址
//所以i++ 就直接给内存地址赋值就可以了
for(; i<len; i++){
p[i] = rand()%100;
printf("%d, %#x \n", p[i], &p[i]);
}
getchar();
int addLen;
printf("第二次增加数组的长度");
scanf("%d", &addLen);
printf("addLen is %d", addLen);
// realloc 重新分配内存,之前开辟的内存指针,需要扩容或者缩小的大小,
// 扩大会扩大内存
// 1. 如果当前内存段后面有需要的内存空间,直接扩展,返回原指针。
// 2. 当前内存段后面的空闲字节不够,那就是用堆中第一个能满足这一要求的内存区域,
// 把原内存数据copy,然后释放原内存
// 3. 如果申请失败,返回NULL
int* p2 = realloc(p, sizeof(int)*(len+addLen));
if (p2 == NULL){
printf("重新分配内存失败");
}
i = 0;
for (; i<(len+addLen); i++){
p2[i] = rand()%100;
printf("%d, %#x\n", p2[i], &p2[i]);
}
if (p2!=NULL){
free(p2);
p2 =NULL;
}
getchar();
return 0;
}
输出如下:
第一次输入数组的长度2
7, 0xc1500000
49, 0xc1500004
第二次增加数组的长度2
addLen is 2
73, 0xc1500000
58, 0xc1500004
30, 0xc1500008
72, 0xc150000c