这个C语言面试题真的有水平,强烈推荐!

我们说学习的目的是指导实践,其实说白了就是为了以后的工作,也是为了更好的生活。而面试对于工作来说是前提,今天我们就从美国某著名软件企业M公司的面试题说起,一来看看面试题的方向和难度,二来检测一下自己的C语言基础。直接上图,大家看输出什么?(假设int类型和指针类型都为4字节)

       

我们一直说指针是C的核心和灵魂,其实本题考察的主要就是你对指针的理解和掌握程度,同时也涉及了一些关于数组和结构体内存对齐的知识。应该来说,本题如果你能做对,那么你对指针的理解应该差不多了。

代码分析:先来分析一下源代码:p 是一个int型的指针,它指向结构体 s 的 i 成员,接着分别对 p[0] 和 p[1] 赋值1和2。然后又让结构体 s 的 p 成员指向 p,对 s.p[1] 和 s.p[0] 分别赋值为 1 和 2。代码很简单,那究竟会输出什么呢,讲到这里,可能就有很多答案了,但其实编译运行后程序崩溃了,结果令人不解,下面我们就查找一下哪行代码导致的程序崩溃。

     

注意:查找BUG的一个方法是用printf定位到错误代码!行很明显s.p[0]=2这行代码出了问题

      具体分析:main函数中的指针p指向结构体中的i,p[0]=1即i=1,而s.p=p后,即结构体中的指针p指向了i,这都没问题。关键就在s.p[1]=1这句上,我们知道,s.p指向i,s.p[0]应该就是i的值,根据指针的加减法则,指针加减1相当于加减指向数据类型的字节数,因为开头说的int型和指针类型都占4字节,因此p+1就指向了s.p,所以s.p[1]=*(s.p+1)=1=s.p,这道题的关键就是理解这里!

       

这样,s.p相当于指向了内存中为1的地方,而下一语句s.p[0]=2相当于向内存为1 的地方写入2这个值,对计算机来讲,要访问这个内存是非法的,因为内存为1的地方可能储存着其他有用的信息,这其实跟声明指针后未初始化就解引用的道理一样,因此程序崩溃了。

讲到这里,可能会有些争议,有人会说为什么这个程序在我的计算机上没有崩溃(你可以先把程序里所有int改为long long试一下结果),这就是我开头说的本题涉及到结构体中内存对齐的问题了,关于这个问题我们后面有机会再推送详细讲解。所以就有了两种情况:

情况一:当i和指针p所占字节数相同时,也就是都为4时,结构体s在内存中存储图如下,这是p+1就指向了p,因此s.p[1]=1就相当于s.p=1了,接下来程序就崩溃了。

情况二:当i和指针p所占字节数不同时,也就是我们目前大多数64位计算机中int为4,指针为8的情况,结构体存储如下图,此时根据内存对齐原则,i后面还有四个字节,因此p+1不指向p,s.p[1]=1相当于修改了i后面四字节内存中数据的值,而s.p[0]=2相当于修改i的值为2,此时s.p不等于1了,因此程序不会崩溃,这也是大多数人计算机中的情况。

好了,讲到这里,这道题算差不多了,本题的核心是考察指针,也顺便考察了数组和指针的关系、结构体内存对齐等知识点,可以看出面试对基础的要求不低,因此大家在以后的学习中还是要注重基础,基本功一定要打好,大家加油吧!

猜你喜欢

转载自www.cnblogs.com/seal008/p/12395403.html