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

突然之间在网上看见了这道题,感觉还挺好
问题:

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平台下输出啥?

这道题其实还算有点意思??

下面把这道题讲解一下。

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强制转换成整型指针,因此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指向如下图所示:

显然,此时打印的内容就是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)序,就是读取或者存放数据时,最低 位 对应 低地址 。

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

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

到此这个试题基本算是圆满解决了

Last modification:July 27th, 2019 at 04:37 pm
如果觉得我的文章对你有用,请随意赞赏

Leave a Comment

2 comments

  1. newcoderlife

    几种写法看的头晕眼花。要是由我来维护,一定重构之!

    1. 孟超
      @newcoderlife

      >﹏<我抽空重新写写,