C语言程序猿必会的内存四区及经典面试题解析
前言:
为啥叫C语言程序猿必会呢?因为特别重要,学习C语言不知道内存分区,对很多问题你很难解释,如经典的:传值传地址,前者不能改变实参,后者可以,知道为什么?还有经典面试题如下:
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
void getmemory(char *p)
{
p=(char *) malloc();
}
int main( )
{
char *str=NULL;
getmemory(str);
strcpy(str,"hello world");
printf("%s/n",str);
free(str);
return ;
}
这段代码执行了会怎么样?接下里我会解释这道面试题。
一、内存布局
可能网上有很多把内存分的很多、很细,但觉得很难记,并对于理解问题作用并不大。现在主要将内存分为四区如下:
代码区:存放代码;运行期间不可修改
全局区:全局变量、静态变量、常量字符串;程序运行时存在,退出时消失。
栈区:自动变量、函数参数、函数返回值;作用域函数内(代码块内)
堆区:动态分配内存,需手动释放
用交换两个数的程序进行解释吧,如下:
#include<stdio.h> void swap(int a,int b)
{
int temp = a; //栈
a = b;
b =temp;
}
int main()
{
int a=,b=; //栈
printf("a:%d,b:%d\n",a,b);
swap(a,b);
printf("a:%d,b:%d\n",a,b); return ;
}
画个图进行讲解,如下: PS:依旧是全博客园最丑图,不接受反驳!

说明:main函数把a,b的值给了temp函数,temp函数在内部交换了值,并没有影响main函数,并且temp结束,栈上的数据释放。传值不会改变实参。
二、程序示例及面试题讲解
1、传地址交换两个数
在拿传指针的例子来说明一下,如下:
#include<stdio.h> void swap(int *a,int *b)
{
int temp = *a; //栈
*a = *b;
*b =temp;
}
int main()
{
int a=,b=; //栈
printf("a:%d,b:%d\n",a,b);
swap(&a,&b);
printf("a:%d,b:%d\n",a,b); return ;
}
结果:成功交换了实参的值
用图进行解释,如下: PS:依旧是全博客园最丑图,不接受反驳!

说明:实参把地址传给形参,形参*a、*b是取的实参在内存中的值,交换也就是交换实参的值了,所以成功交换了实参的值。
2、解释面试题
程序就是最开始的面试题那个,不再列出来了。
结果:段错误
然后画图进行说明,如下: PS:依旧是全博客园最丑图,不接受反驳!

说明:最重要一点实参是把值传给形参,而不是地址,要理解这一点!就是把实参的NULL给了形参,然后getmemory在堆上开辟空间,结束时p被释放了,但main函数中的str并没有指向堆上的内存,再给strcpy,当然会段错误。
三、解决被调函数开辟空间
可能有人就问了,我就想让被调函数开空间,怎么办呢?那就需要形参是二级指针了。
给大家演示一下,代码如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void getmemory(char **p)
{
*p=(char *) malloc();
}
int main( )
{
char *str=NULL;
getmemory(&str);
strcpy(str,"hello world");
printf("%s/n",str);
free(str);
return ;
}
结果:没有段错误了
大家可以自己画下图,不懂欢迎随时留言。
三、十月份计划
十月份需求会很忙,但也要抽出时间把C++基础学完,然后深入学习数据结构和算法了
C语言程序猿必会的内存四区及经典面试题解析的更多相关文章
- C语言内存四区的学习总结(一)---- 静态区
最近重新学习C语言相关知识,重新提到内存四区的概念,那么在之前的学习的基础上,在这儿做一个简单的总结与分享. 一.内存四区建立的流程 可以简单直观的查看下面的这个图片,直接的说明我们的程序在内存中是如 ...
- 每一个程序猿必知之SEO
似乎由于受这篇文章的影响 http://katemats.com/what-every-programmer-should-know-about-seo/ 于是我也觉得我应该写一个每一个程序猿必知之S ...
- C语言提高 (1) 第一天 数据类型本质与内存四区
(物联网的分层的概念 b/s c/s 结构 习惯: 在C语言 0 函数执行成功 <0是错误 >1做一些返回值处理 3 课前准备 工作经验,记录 4 数据类型的本质 数据类型的本质是固定大小 ...
- 深入理解C语言-深入理解内存四区
数组与指针 当数组做函数参数的时候,会退化为一个指针 此时在函数内是得不到数组大小的 因此,数组做函数参数的时候需要传递数组大小,也就是多传递一个参数 void func(int arr[], int ...
- C语言内存四区的学习总结(三)---- 栈区
接上篇内存四区的堆区的总结,下面做一些栈区的相关总结. 一.栈区的分析: 就下面测试程序 #include "stdio.h" #include "string.h&qu ...
- C语言内存四区的学习总结(二)---- 堆区
接上篇,内存四区的分析-静态区,下面来说明一下堆区总结. 堆区分析: 堆区(heap):一般由程序员分配释放(动态内存申请与释放),若程序员不释放,程序结束时可能由操作系统回 就下面的程序: #inc ...
- C语言进阶之路(一)----C语言的内存四区模型
内存四区模型:操作系统给C/C++编写的程序分配内存,通常将分配的内存划分为以下四个区域:1.栈区:存放局部变量,用完由操作系统自动释放2.堆区:动态分配给程序的内存区域,由程序员手动释放3.数据区: ...
- C语言之内存四区模型和函数调用模型
内存四区模型 流程说明1.操作系统把物理硬盘代码load到内存2.操作系统把c代码分成四个区3.操作系统找到main函数入口执行 1.内存四区: 一个由c/C++编译的程序占用的内存分为以下几个部 ...
- C语言的内存四区模型和函数调用模型
首先是操作系统将代码程序加载到内存中 然后将内存分为4个区 栈区,程序的局部变量区,函数传递的参数,由编译器自动进行内存资源的释放. 堆区,动态内存申请,如果不手动释放内存,则这块内存不会进行析构. ...
随机推荐
- 【java】-- 线程池原理分析
1.为什么要学习使用多线程? 多线程的异步执行方式,虽然能够最大限度发挥多核计算机的计算能力,但是如果不加控制,反而会对系统造成负担. 线程本身也要占用内存空间,大量的线程会占用内存资源并且可能会导致 ...
- c++编辑器配置
notepad++ cmd /k cd /d "$(CURRENT_DIRECTORY)" & g++ "$(FILE_NAME)" -o " ...
- Y1E001 HDI二阶板、三阶板
简单说一下我的理解: 首先我认为几阶就是几次压合,我习惯用几次压合来形容.. 一阶板我认为就是一次压合,只能打一种机械孔,在表层把 一阶板是最普通的的多层板压合方式. 如下图所示,L2~L3为芯板CO ...
- 推荐vim学习教程--《Vim 练级手册》
非常不错的vim学习资源,讲解的简单明了,可以作为速查工具,在忘记时就翻下.地址如下: <Vim 练级手册>
- leetcode 902 数位dp 不包含0
复习了一下数位dp 肯定不包含0,但是通常数位dp最后计算的结果较小的是包含前导0的,只是没显示出来而已,所以这题需要前导0,但是非前导0是不需要算进去的,因此,加个是否是前导0的状态即可 class ...
- async与defer
<script>元素的几种常见属性: async 异步加载,立即下载,不应妨碍页面其他操作,标记为 async 的异步脚本并不保证按照指定的先后顺序执行,因此异步脚本不应该在加载期间修改 ...
- 201771010126 王燕《面向对象程序设计(java)》第十八周学习总结
实验十八 总复习 实验时间 2018-12-30 1.实验目的与要求 (1) 综合掌握java基本程序结构: (2) 综合掌握java面向对象程序设计特点: (3) 综合掌握java GUI 程序设 ...
- 使用getline输入一行字符串
给定10个国家名,按字母顺序输出,国家名中可以包含空格,国家名用换行隔开 #include<algorithm> #include<iostream> #include< ...
- django介绍及路由系统
第一:Python的web框架介绍 Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引 ...
- Flutter 读写本地文件
文档 注意 安装 path_provider 插件后重启f5, 而不是等待热更新 demo import 'dart:io'; import 'dart:async'; import 'package ...