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(不要忘了'')


  • 相关阅读:
    买房的贷款时间是否是越长越好?https://www.zhihu.com/question/20842791
    asp.net cookie and session
    leelazero and google colab
    download file by python in google colab
    physical processor, core, logical processor
    通过powershell操作eventlog
    openxml in sql server
    get the page name from url
    How to Execute Page_Load() in Page's Base Class?
    Difference between HttpContext.Request and Request
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/7183707.html
Copyright © 2011-2022 走看看