zoukankan      html  css  js  c++  java
  • C语言事实上不简单:数组与指针

    之前在写C的时候,没怎么留意数组。就这么定义一个。然后颠来倒去的使用即可了。只是后来碰到了点问题。解决后决定写这么一篇博客,数组离不开指针。索性就放一起好了。

    如今我定义了一个数组:int cc[10];

    环绕这个数组有好几种指针:cc, cc+1, &cc[0], &cc, &cc+1等等。你知道它们都是什么含义吗?试试执行下面带代码:

    #include <stdio.h>
    
    int main()
    {
        int cc[10];
    
        printf("%x
    ", cc);
        printf("%x
    ", cc+1);
        printf("%x
    ", &cc[0]);
        printf("%x
    ", &cc);
        printf("%x
    ", &cc+1);
    
        getchar();
        return 0;
    }
    
    cc,这是学数组时第一个接触的"指针",最为熟悉,它是数组的首个元素。

    cc+1,这是指向数字第二个位置的指针。

    &cc[0],这个事实上就是cc,指向数组的首个元素。

    &cc。这是什么玩意儿?指向指针的指针?

    &cc+1,假设上面的意思是指向指针的指针。那这个岂不是指向野地址了?

    如果执行环境是32位机。而且数组首地址为0x28ff00。那么:

    cc的结果为0x28ff00,这点毫无疑问。

    cc+1的地址是0x28ff04而不是0x28ff01,由于一个int占用了4个字节的空间。cc+1事实上是当成cc+1*sizeof(int)来看待。

    &cc[0]的结果是0x28ff00,cc[0]表示的是数组的首个元素。那么&cc[0]自然就是首个元素的地址了。&cc[0] == cc。

    &cc,这个就难说了。指针cc的值是0x28ff00,&cc表示这个指针本身的地址,我们怎么可能会知道这个地址?输出是个随机地址吗?随机数的话这个输出全然没有意义啊。假设不是随机地址的话,难不成还是0x28ff00?这种话a不就等于&a了?明显不正确吧。

    对于基本类型的指针,如int *tt; 那么*tt是其值,&tt是指针的地址,&tt != tt

    可是上述的cc是个数组。实际上。&cc被编译成了&cc[0],可是其含义不同,&cc指向的是整个数组的开头。

    &cc与cc的指向能够用下图来形象表示:


    上图能够看出,&cc事实上代表的是int(*)[10],那么&cc+1就能够理解为cc + sizeof(cc)/4,之所以除以4是由于int型指针++事实上是移动了4个字节。

    又或者说%cc == cc + sizeof(cc)/4 == cc + 10。所以&cc+1的值为0x28ff28。

    可见我们寻常使用的数组名,并不能单纯的当成指针看待。数组名的本质是代表数组对象的变量名,是一个左值,是一个不能被改变的左值。

    可是因为在程序中不保存数组的大小,所以通过数组名仅仅能訪问数组的左值。不能訪问数组的右值。

    因为这个原因,数组名在作为右值使用的时候被赋予另外一个新的意义——指向数组第一个元素的指针。这就是array-to-pointer转换规则。

    依据标准规定。仅仅有当数组名作为sizeof、&运算符的操作数的时候。它是一个左值,其类型为数组类型。除此之外的全部情况,数组名都是一个右值,被编译器自己主动转换为指针类型,这样的情况下我们就说数组名是一个指针。而且是一个指针常量。



    接下来是另外一些有趣的东西,我们结合sizeof与数组输出各类值。

    下面程序的输出结果是什么?建议思考后再执行程序来验证答案。

    #include <stdio.h>
    
    int main()
    {
        int cc[10];
        printf("%d
    ", sizeof(cc[0]));
        printf("%d
    ", sizeof(cc));
        printf("%d
    ", sizeof(&cc));
        printf("%d
    ", sizeof(int(*)[10]));
    
        getchar();
        return 0;
    }
    
    sizeof(cc[0]),一个int的大小。输出4,没问题。

    sizeof(cc),注意不要和上面搞混。这不是数组首地址的指针,cc在这里是左值。其为数组类型。所以结果为40。

    sizeof(&cc),这个的答案应该是多少呢?注意了。cc在这里还是左值,其为数组类型,但&cc不同于cc,无论数组怎么复杂它始终是个指针,32位机上指针大小始终是4个字节。所以结果为4。

    sizeof(int(*)[10]),这个事实上和上面的&cc是一个样的,代表了整个数组,但还是指针,所以结果相同为4。

    练习:以下的程序输出结果是什么(如果32位机):

    #include <stdio.h>
    
    int main()
    {
        int *p[2];
        printf("%d
    ", *p);
        printf("%d
    ", sizeof(p));
        printf("%d
    ", sizeof(&p));
    
        getchar();
        return 0;
    }
    

    答案是:随机数、8、4

    再来一个练习:下列程序的输出是什么?

    #include <stdio.h>
    
    int main()
    {
        char str[]="hactrox";
        char *p = str;
        printf("%d %d
    ", sizeof(str), sizeof(p));
    
        getchar();
        return 0;
    }
    

    答案:8、4(不要忘了'')


  • 相关阅读:
    Python学习————并发编程
    Python学习————作业
    Python学习————网络编程
    Python学习————异常处理
    Python学习————反射
    Python学习————绑定方法
    Python学习————继承
    1765 谷歌的恐龙
    2504 是子序列的个数
    51Nod2386 分则能成
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/7183707.html
Copyright © 2011-2022 走看看