一、C语言内存分配
- 栈区(stack):windows下,栈内存分配
2M
(确定的常数),超出限制提示stack overflow
错误。自动分配内存,自动释放。 - 堆区(heap):程序员手动分配手动释放,可以分配操作系统80%的内存。
- 全局区或静态区
- 字符常量区
- 程序代码区
二、静态内存分配
声明一个占40M内存的数组:
void main(){
//静态内存分配
int a[1024 * 1024 * 10 * sizeof(int)];
getchar();
}
运行结果:
stack overflow.jpg
超出了栈内存为每个应用程序分配的最大内存,所以提示stack overflow
错误。
三、动态内存分配
需求:在堆内存上分配40M的内存。关键字
malloc
void main(){
//在堆内存上分配40M的内存
malloc(1024 * 1024 * 10 * sizeof(int));
getchar();
}
打开内存管理器:
堆内存2.jpg
我们的应用程序占了40.4M的内存空间。
释放内存空间
关键字free
void heapFun(){
//malloc的返回类型是void *,它代表任意类型的指针
int* p = malloc(1024 * 1024 * 10 * sizeof(int));
//释放
if (p != NULL){
free(p);
p = NULL;
}
}
动态内存分配和静态内存分配的区别
需求:创建一数组,动态指定数组的大小
void main(){
//静态内存分配创建数组,数组的大小是固定的
//int i = 10;
//int a[i];
int len;
printf("请输入数组的长度:");
scanf("%d",&len);
//开辟内存,大小len*4字节
int* p = malloc(len * sizeof(int));
//给数组元素赋值(使用这一块刚刚开辟出来的内存区域)
int i = 0;
for (; i< len; i++){
p[i] = rand() % 100;
printf("%d,%#x\n",p[i],&p[i]);
}
if (p !=NULL){
free(p);
p = NULL;
}
getchar();
}
运行结果:
动态指定数组大小.jpg
总结:
- 静态内存分配,分配内存的大小是固定的。造成的问题:很容易超出栈内存的最大值;为了防止内存不够用会开辟更多的内存,容易浪费内存。
- 动态内存分配,在程序运行过程中动态指定需要使用的内存大小,手动释放,释放后的这些内存还可以被重新使用。
四、重新分配内存
关键字:realloc
void main(){
int len;
printf("请输入数组的长度:");
scanf("%d", &len);
int* p = malloc(len * sizeof(int));
int i = 0;
for (; i< len; i++){
p[i] = rand() % 100;
printf("%d,%#x\n",p[i],&p[i]);
}
int addLen;
printf("请输入数组增加的长度:");
scanf("%d", &addLen);
//内存不够用,扩大刚刚分配的内存空间
//参数一:原来的内存的指针 参数二:内存扩大之后的总大小
int* p2 = realloc(p, sizeof(int)* (len + addLen));
if (p2 == NULL){
printf("重新分配失败,世界那么大,容不下我...");
}
//重新赋值
int j = 0;
for (; j < len + addLen; j++){
p2[j] = rand() % 200;
printf("%d,%#x\n", p2[j], &p2[j]);
}
if (p !=NULL){
free(p);
p = NULL;
}
if (p2 != NULL){
free(p2);
p2 = NULL;
}
getchar();
}
重新分配内存的两种情况:
- 缩小。缩小的那一部分数据会丢失
- 扩大。如果当前内存段后面有需要的内存空间,直接扩展当前内存空间,realloc返回原指针;如果当前内存段后面的空闲字节不够,那么就使用堆中的第一个能够满足这一要求的内存块,将目前的数据复制到新的位置,并将原来的数据块释放掉,返回新的内存地址。
- 如果申请失败,返回NULL,原来的指针仍然有效。
内存分配的几个注意细节:
- 不能多次释放;
- 释放完成后,给指针置空(NULL),标识释放完成;
- 内存泄漏:p重新赋值之后再free,并没有真正释放内存。例子如下
void main(){
int* p = malloc(1024 * 1024 * 10 * sizeof(int));//40M
p = malloc(1024 * 1024 * 10 * sizeof(int) * 2);//80M
free(p);
getchar();
}
image
如上图,我们发现内存并没有被释放。
正确的做法是:
void main(){
int* p = malloc(1024 * 1024 * 10 * sizeof(int));//40M
free(p);
p = NULL;
p = malloc(1024 * 1024 * 10 * sizeof(int) * 2);//80M
free(p);
p = NULL;
getchar();
}
image
五、字符串
使用字符数组来存储字符串
特点:字符串可以被修改
【1】创建方式一
void main(){
//方式一
char str[] = { 'c', 'h', 'i', 'n', 'a','\0' };
printf("%s\n",str);
printf("%#x\n", str);
getchar();
}
运行结果:
image
修改第一个字符为s
void main(){
//方式一
char str[] = { 'c', 'h', 'i', 'n', 'a','\0' };
str[0] = 's';
printf("%s\n",str);
printf("%#x\n", str);
getchar();
}
运行结果:
image
修改成功!!!
【2】创建方式二
void main(){
//方式二
char str[6] = { 'c', 'h', 'i', 'n', 'a' };
printf("%s\n",str);
printf("%#x\n", str);
getchar();
}
运行结果:
image
修改第一个字符为s
void main(){
//方式二
char str[6] = { 'c', 'h', 'i', 'n', 'a' };
str[0] = 's';
printf("%s\n",str);
printf("%#x\n", str);
getchar();
}
运行结果:
image
修改成功!!!
【3】创建方式三
void main(){
//方式三
char str[10] = "china";
printf("%s\n",str);
printf("%#x\n", str);
getchar();
}
运行结果:
image
修改第一个字符为s
void main(){
//方式三
char str[10] = "china";
str[0] = 's';
printf("%s\n",str);
printf("%#x\n", str);
getchar();
}
运行结果:
image
修改成功!!!
使用指针存储字符串
特点:字符串不可以被修改
void main(){
//内存连续排列
char* str = "how are you";
printf("%s\n",str);
printf("%#x\n", str);
}
运行结果:
image
试试修改第一个字符为w
运行结果:
image
修改失败!!!
我们来试试指针的加法截取字符串
void main(){
//内存连续排列
char* str = "how are you";
printf("%s\n",str);
printf("%#x\n", str);
//使用指针加法截取字符串
str += 4;
printf("%s\n",str);
getchar();
}
运行结果:
image
六、常见的字符串函数
在线API文档:
http://www.kuqin.com/clib/string/strcpy.html
【1】strcat 字符串拼接函数
void main(){
char dest[50];
char* a = "china";
char* b = " is powerful";
strcpy(dest, a);
strcat(dest, b);
printf("%s\n",dest);
getchar();
}
运行结果:
image
【2】strchr 在一个字符串中查找给定字符的第一个匹配之处
void main(void){
char *str = "I want go to USA!";
char* p = strchr(str, 'w');
if (p){
printf("索引位置:%d\n", p - str);
}
else{
printf("没有找到\n");
}
system("pause");
}
运行结果:
image
【3】strstr 从字符串haystack中寻找needle第一次出现的位置
void main(void){
char *haystack = "I want go to USA!";
char *needle = "to";
char* p = strstr(haystack, needle);
if (p){
printf("索引位置:%d\n", p - haystack);
}
else{
printf("没有找到\n");
}
system("pause");
}
运行结果:
image