啊C啊C我爱你-2

C++软件与嵌入式软件面经解析大全(蒋豆芽的秋招打怪之旅)


本章讲解点

  • 1.1 熟悉的陌生人——main函数

  • 1.2 If else——易错细节分辨

  • 1.3 Switch、break——相爱相杀的故事

  • 1.4 For、while、do-while——傻傻分不清楚

  • 1.5 枚举

  • 1.6 结构体与共用体

  • 1.7 函数——原来你是这样的函数

  • 1.8 全局变量与静态变量详解

  • 1.9 数据类型详解

  • 1.10 类型转换

  • 1.11 谁先谁后——把人搞疯的优先级

  • 1.12 震惊——位运算还可以这样用

  • 1.13 面试技巧讲解

  • 1.14 数组指针与指针数组

  • 1.15 指针与字符串

  • 1.16 指针与函数

  • 1.17 指针与结构体

  • 1.18 内存布局

  • 1.19 野指针与内存泄露

  • 1.20 野指针与内存申请

  • 1.21 内存碎片


受众:本教程适合于C/C++已经入门的学生或人士,有一定的编程基础。

本教程适合于互联网嵌入式软件求职的学生或人士。

img

故事背景

img

蒋 豆 芽:小名豆芽,芳龄十八,蜀中人氏。卑微小硕一枚,科研领域苟延残喘,研究的是如何炒好一盘豆芽。与大多数人一样,学习道路永无止境,间歇性踌躇满志,持续性混吃等死。会点编程,对了,是面对对象的那种。不知不觉研二到找工作的时候了,同时还在忙论文,豆芽都秃了,不过豆芽也没头发啊。

隔壁老李:大名老李,蒋豆芽的好朋友,技术高手,代码女神。给了蒋豆芽不少的人生指导意见。

导 师:蒋豆芽的老板,研究的课题是每天对豆芽嘘寒问暖。

img

故事引入

img

蒋 豆 芽:今天周五了,嘿嘿,周末要到了,趁着周末好好复习下,迎接下周的笔试面试,刚把跌!!!(豆芽脸上笑嘻嘻(#^.^#))


蒋 豆 芽:老李,马上周末了,上次你给我讲的C语言细节知识,还有吗?再给我讲讲吧。大佬,哦呐桑(姐姐),拜托。

隔壁老李:(一脸嫌弃)本来是周末陪男朋友的,看你这么诚恳,就给你讲讲吧,我让男朋友晚点来。

蒋 豆 芽:(小声嘀咕)原来如此,呵,女人,重色轻友。

隔壁老李:(目光凌厉)你说啥?

蒋 豆 芽:(一脸嬉笑)没啥啊,我说你才貌与智慧并重,狭义与柔情化身。豆芽滞销,快救救豆芽吧,求求了。

隔壁老李:(一脸无奈)行啦行啦,豆芽,我们就开始吧。

蒋 豆 芽:好好好!


隔壁老李:上次我们一直探讨了一些C语言的细节知识,如果忘了,豆芽你再回去复习复习,这次我们接着讲几个内容。

img

1.7 函数——原来你是这样的函数

img

隔壁老李:上次我们将了熟悉的陌生人——main函数。这次我们讲讲函数的细节知识。

隔壁老李:讲之前,关于函数的基础知识,我们先提一下。函数是一个独立的代码块,实现某一功能,可以传入参数,返回结果。函数定义的一般格式是:

返回值类型 函数名([形参]){  
    函数体  
}  

函数可以没有返回值。

行,豆芽,C语言你是有基础的,所以这里点到为止。

隔壁老李:豆芽,函数的入门知识你应该是没问题的,但是有一个东西不知道你有没有注意过,那就是实参与形参

蒋 豆 芽:这个简单,比如一个函数声明为:double cylinder(double r, double h),这个时候rh就是形参,而当我们调用该函数时,如volume = cylinder(radius, height),这个时候传入的参数radiusheight就是实参。函数调用时,实参radiusheight的值将被依次传给形参rh

蒋 豆 芽:函数的形参必须是变量,用于接受实参传递过来的值;而实参可以是常量、变量或表达式,其作用是把常量、变量或表达式的值传递给形参。如果实参是变量,它与所对应的形参是两个不同的变量

比如:

//函数声明,函数的形参必须是变量
double cylinder(double r, double h);

//函数调用,实参可以是常量、变量或表达式
volume = cylinder(radius, height);
volume = cylinder(3, 4);
volume = cylinder(radius+3, height*4);

实参是主调函数的,形参是自定义函数的,这两者可以同名,也可以不同名实参和形参一一对应,数量应相同,建议类型也保持一致。

隔壁老李:豆芽,你的基础还不错嘛。

蒋 豆 芽:嘻嘻。勉强勉强。

隔壁老李:那我问下你,以你的例子为例,当rh的值改变时,radiusheight的值会改变吗?

蒋 豆 芽:(不太确定)不会吧。

隔壁老李:你的样子看起来不太确定哈。正确答案是不会的。我们在学习语言时,都会想当然先入为主,平时习以为常,并没有去关注细节,但是有人问起细节时,就感觉不确定了,所以我们要弄懂细节,使得我们更有自信地去用好一门语言,笔试面试更不在话下。

隔壁老李:豆芽你来说说radiusheight的值为什么不会改变。

蒋 豆 芽:我想起来了,因为在函数传参的过程中,函数会为形参申请新的内存空间,并将实参的值复制给形参。如下:

img

因为实参和形参是不同的变量,各自占有自己的内存,当然形参的值发生改变但不会影响实参了啊。

隔壁老李:没错,我们来验证一下。下面是我给的参考例子。

#include <stdio.h>  
using namespace std;  
double cylinder(double r, double h) {  
    double *address_r = &r;//展示地址  
    double *address_h = &h;  
    r = 1.1; h = 2.2;//改变形参值  
    return 1.0;  
}  
int main() {  
    double radius = 3.2;  
    double height = 4.2;  
    double *address_radius = &radius;//展示地址  
    double *address_height = &height;  
    double volume = cylinder(radius, height);  
    return 0;  
}  

我们通过断点调试,先到double volume = cylinder(radius, height);处,我们先记录一下radiusheight的值和地址,

img

然后进入cylinder函数。

记录一下rh的值和地址:

img

我们可以清楚看到,C语言将实参的值复制给了形参,专门为形参变量开辟了新的内存空间,实参与形参的内存地址是不一样的。然后我们运行完cylinder函数时,我们的形参值发生了改变,最后我们退出函数,发现我们的实参值是没有改变的。

原因很简单,形参和实参拥有不同的内存空间。

img
img

隔壁老李:(眼光一闪)豆芽,我问你个问题,那如果我们想让实参随着形参的值改变应该怎么办呢?

蒋 豆 芽:(丝毫不慌)那就使用指针变量。如double cylinder(double *r, double *h),当我们调用该函数时传入变量地址,volume = cylinder(&radius, &height)

隔壁老李:没错,那我们再来验证一下。

#include <stdio.h>  
using namespace std;  
double cylinder(double *r, double *h) {  
    *r = 1.1; *h = 2.2;//改变形参值  
    return 1.0;  
}  
int main() {  
    double radius = 3.2;  
    double height = 4.2;  
    double *address_radius = &radius;//展示地址  
    double *address_height = &height;  
    double volume = cylinder(&radius, &height);  
    return 0;  
}  

依然按照我们之前的思路依次查看形参实参的地址和值。

img
img
img

可以非常清楚地看到,这时的形参和实参内存地址是一样的,那么改变形参的值,实参的值也会被改变。豆芽你说说这是为什么?

蒋 豆 芽:根据指针的特性,是因为函数调用时,将实参地址赋值给了形参变量,使得形参指针指向了实参的地址空间,所以实参和形参指向了同一个内存空间。如图:

img

可以很清楚地看到,函数为形参*r申请新的内存空间,然后将实参radius的地址赋值给了r,所以r=0x0001,这样r就指向了radius的内存空间,通过改变*r的值,也就是改变了radius的值,因为它们指向了同一个内存空间

隔壁老李:豆芽,那你看看下面的代码,最后radiusheight的值又是多少呢?

#include <stdio.h>  
using namespace std;  
double cylinder(double *r, double *h) {  
    r = new double(0.1); h = new double(0.2);  
    *r = 1.1; *h = 2.2;//改变形参值  
    return 1.0;  
}  
int main() {  
    double radius = 3.2;  
    double height = 4.2;  
    double *address_radius = &radius;//展示地址  
    double *address_height = &height;  
    double volume = cylinder(&radius, &height);  
    return 0;  
}  

蒋 豆 芽:这不是一样的吗?指针形参嘛,最后radius=1.1height=2.2

隔壁老李:你确定吗?我们看看最后的结果吧

img

蒋 豆 芽:(一脸疑惑)咦?没变?形参不是值改变了吗?这是怎么回事?

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

<p> - 本专刊适合于C/C++已经入门的学生或人士,有一定的编程基础。 - 本专刊适合于互联网C++软件开发、嵌入式软件求职的学生或人士。 - 本专刊囊括了C语言、C++、操作系统、计算机网络、嵌入式、算法与数据结构等一系列知识点的讲解,并且最后总结出了高频面试考点(附有答案)共近400道,知识点讲解全面。不仅如此,教程还讲解了简历制作、笔试面试准备、面试技巧等内容。 </p> <p> <br /> </p>

全部评论
func3为啥是10不是30呀,有大佬能细说嘛
1
送花
回复
分享
发布于 2021-06-17 22:53
哈哈哈 太搞笑了
点赞
送花
回复
分享
发布于 2023-08-25 17:33 湖北
秋招专场
校招火热招聘中
官网直投
小笔误:强制类型转换int sum = 17;应该是7
点赞
送花
回复
分享
发布于 03-15 11:53 江苏

相关推荐

头像
04-02 20:00
点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务