C语言 - -内存四区总结

内存四区

程序的内存四区模型

执行程序的过程

  1. 操作系统把 代码从硬盘 load(加载)到内存中
  2. 操作系统把代码分成四个区
    • 栈区:由编译器自动分配释放,存放函数的局部变量、参数值。
    • 堆区:由程序员分配释放,主要是一些动态分配的函数(malloc….),如果程序员不手动释放的话,会等到程序结束空间才会释放。
    • 全局区:存放全局变量,静态变量,字符串常量区,程序结束之后才会释放
    • 代码区:存放程序的二进制代码
  3. 操作系统找到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
  1. 由上面代码可知,指针变量a里面存的仅仅只是第一个字符的地址

    那么就可以得出char*a = “abcdef”仅仅是把该字符串的首地址付给了a

  2. “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”

这里引号有几个作用:

  1. 在文字常量区申请空间,存放字符串
  2. 在字符串结尾加上‘\0’
  3. 返回地址

**注意:**数组不能这样初始化

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
说明:该代码说明虽然字符串都是一样的,但是他们存储的地方不一样

本人第一次发博客,如有问题,请指正,我会及时更改

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值