内存四区
程序的内存四区模型
执行程序的过程
- 操作系统把 代码从硬盘 load(加载)到内存中
- 操作系统把代码分成四个区
- 栈区:由编译器自动分配释放,存放函数的局部变量、参数值。
- 堆区:由程序员分配释放,主要是一些动态分配的函数(malloc….),如果程序员不手动释放的话,会等到程序结束空间才会释放。
- 全局区:存放全局变量,静态变量,字符串常量区,程序结束之后才会释放
- 代码区:存放程序的二进制代码
- 操作系统找到main函数入口执行
全局区分析
代码
//内存四区中的全局区分析
# include <stdio.h>
char * getn1(void)
{
char *p = "abcdef";
return p;
}
int main (void)
{
char *p = NULL;
p = getn1();
printf ("d = %d,s = %s\n",p,p);
return 0;
}
输出结果为:d = 850358276,s = abcdef
关于上面代码中第六行字符串赋值给字符指针的理解
https://www.cnblogs.com/clemente/p/10755964.html
栈区分析
代码
# include <stdio.h>
# include <string.h>
char *get_str(void);
int main (void)
{
char num[100] = {0};
strcpy(num,get_str());
printf ("%s",num);
return 0;
}
char *get_str(void){
char m[]= "abcdef";
return m;
}
堆区分析
# include<stdio.h>
# include<malloc.h>
# include<string.h>
char* get_arr(void)
{
char *p = (char*)malloc(100);
if( p == NULL)
return NULL;//如果分配失败,则返回空
strcpy (p,"abcdef");
// p = "abcdef";
return p;
}
int main (void)
{
char*q = NULL;
q = get_arr();
if(q != NULL)
printf ("%s",q);
free(q);/*
这里不能使用free(p);
因为p不是main里面的变量,而是get_arr里面的变量
在main函数中q指向了这段动态分配的空间,所以free(q)就能够释放掉get_arr函数里面分配的空间.
free(),释放变量所指向的空间
*/
q = NULL;
return 0;
}
内存四区 总结疑惑点
char* p = “abcdef”,为什么可以这样,这两个数据类型不是不一样吗
参考https://www.cnblogs.com/clemente/p/10755964.html
# include<stdio.h>
int main (void)
{
char *a = "abcdef";
printf ("%c\n",*a);
printf ("%c\n",*(a+1));
printf ("%s\n",a);
return 0;
}
# 输出结果为:
a
b
abcdef
由上面代码可知,指针变量a里面存的仅仅只是第一个字符的地址
那么就可以得出char*a = “abcdef”仅仅是把该字符串的首地址付给了a
“abcdef” 出现在表达式中仅代表该字符串首字符的地址
3.字符串"abcdef"中引号的功能可以看做:
- 为字符串申请了空间
- 为字符的末尾加上了’\0’
- 将首地址赋值给指针变量
%s可以直接打印出指针吗?为什么%d打印出来的是指针的地址(十六进制数)
# include<stdio.h>
int main (void)
{
char *a = "abcdef";
int *b;
int c = 12345;
b = &c;
char arr[100] = "abcdef";
printf ("%s\n",arr);
printf ("%s\n",a);
// printf ("%s\n",*a);错误,无输出
printf ("%d\n",b);
printf ("%d\n",*b);
return 0;
}
输出结果为:
abcdef
abcdef
-1281676988
12345
%s本来是打印字符串的,他需要一个指针变量(也就是数组首元素的地址)来寻找数组,然后打印直到结束字符‘\0’截止,所以他的打印对象就是指针().然后就能打印出a所指向数组的值,就和第10行打印出arr数组是一样的
%d的打印对象是变量,直接打印出变量的值
字符数组和字符指针
初始化
char arr [100] = “abcdef”
数组的初始化,是将在文字常量区的 “abcdef” 拷贝到 在栈区分配的100字节空间中,然后将首地址赋值给 arr
这里的使用的arr已经是栈区的字符串了,而不再是文字常量区的“abcdef”
char * a = "abcdef"
这里是将在文字常量区的“abcdef”的首地址赋值给a,a就指向了“abcdef”
这里引号有几个作用:
- 在文字常量区申请空间,存放字符串
- 在字符串结尾加上‘\0’
- 返回地址
**注意:**数组不能这样初始化
arr = "abcdef"
因为arr是一个地址,是常量,不能给他赋值,而a是一个指针变量,可以给他赋值
使用
字符数组只能在本函数内使用,不能在其他函数内使用,除非定义了全局变量,他在栈区,所在函数结束之后就会释放
字符指针可以在所有函数内使用,因为他在文字常量区,全局区只有在程序结束之后才会释放
打印
都可以使用%s来打印
int main (void)
{
char *p = "abcdef";
char arr [100] = "abcdef";
printf ("p = %p\n",p);
printf ("arr = %p\n",arr);
return 0;
}
输出结果:
p = 0x559359449004
arr = 0x7ffcfb7a9d40
说明:该代码说明虽然字符串都是一样的,但是他们存储的地方不一样
本人第一次发博客,如有问题,请指正,我会及时更改