【内功篇】指针&数组&字符串(四)

上一篇介绍了指针数组和数组指针,那么数组就告一段落了,这篇将回归指针。


类型强制转换:

我们知道C语言的基本数据类型之间能够进行强制转换。其实,指针之间也能进行类型强制转换,但是意义并不一样。我们知道指针里保存的是一个地址,不管什么类型的指针存的都是地址,所以再怎么转换地址是不会变得,长度也不会变,贴段代码:

#include <stdio.h>

int main()
{
    int a;
    int  *p1 = &a;
    char *p2 = (char *)p1;

    printf ("%p\n",p1);
    printf ("%p\n",p2);
    printf ("%d\n",sizeof(p1));
    printf ("%d\n",sizeof(p2));

    return 0;
}

打印下结果
这里写图片描述
怎么样,结果和说的一样吧,那么,这个强行转换究竟干了些啥呢。我们知道int *p中int的意思吧,就是指针所指地址内数据的类型,有了这些类型,在用*p取数据的时候才知道该往后取几个字节才能获得自己想要的数。强转干的就是这个事,贴段代码:

int main()
{
    int a;
    int  *p1 = &a;
    char *p2 = (char *)p1;

    printf ("p1 = %p\n",p1);
    printf ("p2 = %p\n",p2);
    printf ("p1+1 = %p\n",p1+1);
    printf ("p2+1 = %p\n",p2+1);

    return 0;
}

打印下结果:
这里写图片描述

看出什么门道了么,没错,p1,p2向右偏移一位时偏移的字节数不一样,可以看出p1偏移了4个字节相当于一个int的字节数,而p2偏移了1个字节相当于一个char的字节数,这下好理解了,继续看段代码:

int main()
{
    int a = 10;
    int  *p1 = &a;
    char *p2 = (char *)p1;

    printf ("%d\n",*p1);
    printf ("%d\n",*p1);

    return 0;
}

打印下结果:
这里写图片描述
结果一样啊,那我们再看:

int main()
{
    int a = 256;
    int  *p1 = &a;
    char *p2 = (char *)p1;

    printf ("%d\n",*p1);
    printf ("%d\n",*p2);

    return 0;
}

打印下结果:
这里写图片描述

咦,怎么是这样呢,我们从内存来分析下原因。
这里写图片描述

上图是a = 10的时候内存里存储情况,注意,我用十六进制数表示了。

这里写图片描述

上图是a = 256时候内存里的存储情况,是不错看起来存的很奇怪,注意:我用的机子是小端模式,数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。大部分的CPU都是小端模式,当然通过程序可以测出。

回归正轨,通过两幅图可以看出来了么,相信仔细的分析一下就应该理解了吧,我就不过多的说明了。

这有一题从书上看到的题目,可以加深一下理解:

int main()
{
    int a[4] = {1, 2, 3, 4};
    int *ptr1 = (int *)(&a + 1);
    int *ptr2 = (int *)((int)a + 1);

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

    return 0;
}

结果是啥呢?

这里写图片描述

第一个输出的是4相信大家都知道吧,那么这个2000000哪来的呢,我们来看看内存情况。

这里写图片描述

首先看(int)a + 1,这里的int已经将a地址转换成整型,这时候它是一个数,而不是地址,加上一然后再由(int *)强转为一个地址,是不是就相当于由a的地址向后移动了一位,然后是指针指向的地址内的数据是整型,所以从当前地址向后取4个字节的内容00 00 00 02,输出的时候经过自动的整理得到02 00 00 00既2000000,注意哦,这里的输出用%x表示输出的是十六进制数,刚好,我在内存里也用十六进制存(当然只是看着是,其实内存里真正存的还是二进制)。

未完待续…………

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值