`
fp_moon
  • 浏览: 971475 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

一道C语言试题 ---转

c 
阅读更多


int main(void)

{

    int a[4] = {1, 2, 3, 4};

    int *ptr1=(int *)(&a+1);

    int *ptr2=(int *)((int)a+1);

    printf("%x, %x/n", ptr1[-1], *ptr2);

    return 0;

}

问,在x86平台下输出啥?


 

题目虽然恶心了点,但作为一个例子来分析,还是挺好玩的。学过C语言的朋友可以暂且不看下文,自己试着分析一下,看看结果跟我的是否一样,也不失为一件趣事。

下面把这道题牵涉到的所有边边角角的问题梳理一遍,详细讨论如下:

1、&a+1

首先明确,a是一个具有4个整型变量的数组的名字,具体地说是这种数组的首元素的首地址,而&a是数组的首地址,请注意措辞。而关于指针加1,则需要指针运算的知识。没学过指针运算或者已经忘记了这个知识点的朋友们,下面就是关于指针运算你需要知道的事实:

就像上面的例子那样,式子&a+1表示的是指针加法运算,而不是普通的数值加法运算,之所以会这样是因为&a是一个指针而非普通数值(虽然它本质上也是一个整数)。那么你会问:加入此时&a=0xFFFF5700,那么&a+1是多少呢?答案是:取决于&a的类型 

    a) 如果&a是一个指向char型的指针,那么&a+1 = 0xFFFF5701

    b) 如果&a是一个指向short型的指针,那么&a+1 = 0xFFFF5702

    c) 如果&a是一个指向int型的指针,那么&a+1 = 0xFFFF5704 (32位机器)

    d) 如果&a是一个指向某种结构体struct foo的指针,那么&a+1 = 0xFFFF5700+sizeof(struct foo)

    ……

还没看出端倪吗?没错,指针加1不是指针内容简单地加1,而是让指针指向下一个数据 ,加2就是让指针指向下两个数据,这个数据的类型就是指针指向的类型,所以指针的加法究竟会让这个指针指向哪里,取决于这个指针指向的数据类型。

 

因此,综上所述,当&a与整数1做加法时,实际上是指针的加法,加1的含义是:令指针a指向下一个数据 ,下一个数据是啥?当然是紧挨着的下一个具有4个整型变量的数组了(因为&a的类型是指向具有4个整型变量的数组的指针嘛),于是a的指向了4的下一个地址,在用此值初始化ptr1,因此ptr1的指向如图所示:

图片

由于在ptr1初始化的时候,令&a+1强制转换成整型指针(关于类型转换的详细讨论请参考http://blog.csdn.net/seton040/archive/2009/10/19/4699869.aspx),因此ptr1[-1]相当于把ptr1往前挪一个整型大小,即4个字节。 如下图:

图片

显然,打印出的第一个数字是a[3]的内容,即数值4.

当然,我们还必须说明一个事实:数组下标是可以为负数的,实际上,取下标符“[ ]”的内部实现,就是指针运算!比如a[2],等价于*(a+2),即以a地址为基址,取偏移量为2的地址的值。所以ptr1[-1]等价于*(ptr-1)。

 

2、(int *)((int)a+1)

至于指针ptr2的处理更恶心一点,呵呵!它先是把数组名a强制转换成整型变量,然后再加1,然后再强制转换成整型指针!真罗嗦,但不要紧,咱有的是耐性,无非就是让ptr2指向a[0]的第二个字节罢了,此时ptr2指向如下图所示:

图片

显然,此时打印的内容就是ptr2所指向的往后4个字节的内容了,也就是a{0}的后三个字节和a[1]的第一个字节,那究竟会打印出啥玩意儿呢?上面的图没有画出里面的内容,要是把每个字节的内容都画出来就好了,呵呵!

 

要把上图中每一个字节的内容都打印出来没问题,但是你先要知道字节序 的概念,字节序分两种,一种叫大端字节序(big-endian) ,当然除此之外必然有小端 字节序(little-endian) ,让我们用一个问题,来引出字节序的概念,然后再来搞定这两个小鬼吧!

 

问题是这样的:对多字节存储的变量,机器是如何做出解释的??请看下图:

图片

假如这是一个普通的int变量,地球人都知道,在32机器上int占用4个字节存储数据,就像上图中显示的那样,在4个字节中放置了一堆数字,但是机器究竟会把这个数解释成0x0103070F呢,还是解释成0x0F070301呢?答案是:都有可能!

官方解释:

    1、所谓大端(big-endian)序,就是高优先位 对应高有效位 

    2、所谓小端(little-endian)序,就是高优先位 对应低有效位 

民间解释:

    1、所谓大端(big-endian)序,就是读取或者存放数据时,最低  对应 高地址 

    2、所谓小端(big-endian)序,就是读取或者存放数据时,最低  对应 低地址 

如,要把0x0103070F存放进存储器中时,如果把0E放进高地址处则是小端序,如果把0F放进低地址处则是大端序。照此,上图中存放的数据如果被机器理解成0x0103070F则是该机器是大端序的,否则若被理解成0x0F070301则是小端序的。

 

回到原来的问题,此时ptr2指向了a[0]的第二个字节。我们以x86平台为例(小端序),此时其内部数据分布是这样的:

图片

由于x86平台是小端序的,根据咱刚刚讨论过的理论,小端序的存取时最低  对应 低地址 ,因此将会打印出0200 0000,如果题目中没有说明在x86平台,那答案是不确定的,取决于具体的平台,例如ARM平台就是大端序的。

 

到此这个试题基本算是圆满解决了,但是我还想再罗嗦一下,关于代码中的那个a,以及那个&a,估计还是有很多朋友心里不怎么平坦吧,每次遇到数组啊指针啊,虽然程序好像仿佛貌似也没出啥毛病,但总感觉是混过去的,这次我们要彻底解决它。记得某人说过,一个真正的程序员,必须对自己写的代码的每一个细节了如指掌。

再来考虑这个定义:

 


 

int a[4] = {1, 2, 3, 4};

 


这时我们必须明确,编译器根据我们提供的类型和数组大小,为我们分配了适当大小的存储区域,并且把这块存储区域叫做a,请注意 :&a,就像我们上面提到的,它的类型是“指向具有4个整型变量数组的指针“,简而言之&a是一个数组指针。这个数组的名字a,当它作为右值(简单而言,出现在赋值号“=”左边的就是左值,出现在赋值号“=”右边的就是右值)时代表的是数组首元素的首地址,而不是数组的首地址。此时a的意义跟&a[0]是等价的,都是指向首元素的指针。记住咯!

数组的名字会在另一个地方与指针等价,那就是函数参数表,当出现在函数的参数表里面的时候,不管你写的是数组,还是指针,一旦进入函数内部,通通变成指针。

分享到:
评论

相关推荐

    c语言资料-c嵌入式C精华

    一道著名外企面试题的抽丝剥茧 ......................................................................74 C/C++结构体的一个高级特性――指定成员的位数 ........................................................

    这是一道c语言的试题

    对于初学者学C语言,是非常好的一道题目的

    嵌入式C语言精华+.pdf

    一道著名外企面试题的抽丝剥茧 ......................................................................74 C/C++结构体的一个高级特性――指定成员的位数 .........................................................

    二级C语言上机试题汇编

    本题库是针对2008年4月份考试的上机考试题库,本题库共有100套题目(每套题目包含3道题:一道程序填空题、一道程序修改题、一道程序设计题),真实考试的时候,考生输入准考证后计算机随机为你抽取一套考试,每个...

    C语言深层探索+ARM linux移植

    C/C+语言struct深层探索 ...从两道经典试题谈C/C++中联合体(union)的使用 149 深入浅出Linux设备驱动编程 151 1.Linux内核模块 151 2.字符设备驱动程序 153 3.设备驱动中的并发控制 158 4.设备的阻塞与非阻塞操作 165

    全国计算机二级C语言全真模拟考试软件下半年版v2014安装版

    需要的朋友赶紧下载试一试吧,希望可以对大家有所帮助的全国计算机等级考试二级C语言全真模拟考试软件与其它同类软件相比具有如下特点: (1)功能全面:软件具有全真模拟、精选习题、详尽解析的功能,每一道试题

    全国计算机等级考试二级C语言全真模拟考试软件v2015上半年版中文安装版

    需要的朋友们可以下载试试吧全国计算机等级考试二级C语言全真模拟考试软件与其它同类软件相比具有如下特点: (1)功能全面:软件具有全真模拟、精选习题、详尽解析的功能,每一道试题都有详细分析,操作题都有

    全国计算机等级考试二级C语言全真模拟考试软件v2015下半年版免费安装版

    全国计算机等级考试二级C语言全真...全国计算机等级考试二级C语言全真模拟考试软件与其它同类软件相比具有如下特点: (1)功能全面:软件具有全真模拟、精选习题、详尽解析的功能,每一道试题都有详细分析,操作题都

    C语言笔试题目

    二级C语言上机试题汇编 ※※※※※※※※※※※※※※※※※※※※※※※※、、、、 第01套: 给定程序中,函数fun的功能是:将形参n所指变量中,各位上为偶数的数去 除,剩余的数按原来从高位到低位的顺序组成一...

    二级C语言上机题100道.doc

    说明:本题库是针对2008年4月份考试的上机考试题库,本题库共有100套题目(每套题目包含3道题:一道程序填空题、一道程序修改题、一道程序设计题),真实考试的时候,考生输入准考证后计算机随机为你抽取一套考试,...

    试卷管理系统 (C语言)程序设计实验 源文件.zip

    功能:(1)试题添加:向试题库追加写入一道新的题目,要求题目编号自动生成,且与已存题目的编号不重复;所有内容不能为空。即不断充实题库;(2)试题删除:通过题目编号进行题目的删除,如果删除成功则提示删除...

    计算机等级考试题库系统(二级C)

    (1)精选700余道C语言笔试试题和45道上机试题,其中包括近两年全国计算机等级考试试题。(2)提供分类检索功能,分类科目按全国计算机等级考试大纲设计,每一道试题均给出答案和评析。(3)互动问答,精彩编程,生动有趣...

    计算机等级考试题库系统 二级C

    (1)精选700余道C语言笔试试题和45道上机试题,其中包括近两年全国计算机等级考试试题。(2)提供分类检索功能,分类科目按全国计算机等级考试大纲设计,每一道试题均给出答案和评析。(3)互动问答,精彩编程,生动有趣...

    嵌入式系统C语言精华

    一道著名外企面试题的抽丝剥茧......................................................................74 C/C++结构体的一个高级特性――指定成员的位数..........................................................

    android和java面试大全集

    C语言终极面试宝典.doc Java笔试题目汇总.pdf Java面试宝典_2010.doc 面试全攻略100题.doc 智力题和答案.doc C语言面试题大汇总.doc 计算机专业必备笔试面试锦囊.doc 笔试.rar 面试题集合.zip C语言面试题大汇总1....

    单项选择题标准化考试系统.doc

    (4)答題:每次显示一道题,用户可实现输入自己的答案。 (5)自动判卷:系统可根据用户答案与标准答案的对比实现判卷并给出成绩。 拓展功能: 随机抽题,即根据用户的输入的题目数随机抽取题目组成一套试卷,在规定的时间...

    嵌入式C_C++语言精华.pdf

    一道著名外企面试题的抽丝剥茧 ......................................................................74 C/C++结构体的一个高级特性――指定成员的位数 .......................................................

    南京摩托罗拉笔试题(今年10月21日的笔试)

    南京摩托罗拉笔试题(10月21日的笔试) 主要招聘软件开发人员,笔试的题目也都是编程方面的 有C语言编程和JAVA编程,还有无线网络方面的基础知识,最后是一道智力题,内容大概如下: ............

    嵌入式C_C++语言精华文章集锦

    一道著名外企面试题的抽丝剥茧 ......................................................................74 C/C++结构体的一个高级特性――指定成员的位数 ........................................................

    嵌入式C/C++语言开发精华文章集锦(嵌入式C/C++开发者必看,很有价值的文章)

    从两道经典试题谈 C/C++中联合体(union)的使用. 基于 ARM 的嵌入式Linux 移植真实体验 基于 ARM 的嵌入式Linux 移植真实体验(1)――基本概念 基于 ARM 的嵌入式Linux 移植真实体验(2)――BootLoader 基于 ARM...

Global site tag (gtag.js) - Google Analytics