zoukankan      html  css  js  c++  java
  • 数组和指针

    1.从内存和编译器角度来理解数组

    1.1内存角度和编译器角度

    (1)定义五个变量,普通定义int a,b,c,d,e;和数组定义int a[5];

    1.都是定义了五个变量,第一种方法定义的变量的内存地址不一定是连续的,第二种方法定义的元素一定是地址连续的。
    2.对于编译器来说,定义数组和定义其他变量的本质都是一样的。

    1.2来理解一些符号 a,a[0],&a,&a[0]分别和左值右值的关系

    分析
    1.(1)a做左值。数组名a做左值时表示数组的所有地址,比如:int a[5];数组名a做左值时表示的就是4*5个内存地址。我们在操作数组的时候只能操作其中的一个元素,不能整体操作。比如 a = {1,2,3,4,5};整体操作是不行的。需要注意的是:它和数组定义初始化int a[5]={1,2,3,4,5}是不同的。

    (2)a做右值。数组名a做右值时,表示数组首元素的首地址,第一个元素可能占好多地址,在这里只表示第一个字节的地址。其类型是数组元素的类型的指针。而非数组指针。

    2.(1)a[0]做左值,表示第一个元素的地址,当a[0] = 1;时,是把1写入到元素a[0]对应的那个内存地址中去。
    (2)a[0]做右值时,test = a[0]; 表示把a[0]的值写入test的地址中去。

    3.(1)&a不能做左值,a的地址是随机分配的,但是一旦分配之后,在程序执行的时候,a的地址已经确定,所以成了常量,常量不能做左值。
    (2)&a做右值,表示,整个数组的首地址。也就是一个指向数组的指针,所以&a做右值时的类型是数组指针。也就是int (*)[]类型。

    4.(1)&a[0]不能做左值,道理和&a一样,变成了常量。
    (2)&a[0]做右值时,表示数组首元素的首地址。

    总结:
    (1)a,&a,&a[0]在数值上是相等的,但是类型和含义完全不同。
    (2)a和&a做右值的区别。a代表数组首元素的首地址,类型是int* 。&a表示数组的首地址,类型是int(*)[];
    (3)a和&a[0]做右值时都是表示数组首元素的首地址。

    2.从数组和指针的角度理解数组

    1.通过代码看数组和指针的关系

    #include<stdio.h>
    
    void main(void)
    {
        int a[5] = {1,2,3,4,5};
        int *p = a;         //将数组名a的值赋值给指针p
                            //数组名a做左值时表示数组首元素的首地址类型是int*
                            //所以这里 a 和 p 类型一致
        //通过数组下标访问元素
        printf("通过数组下标方式:第2个元素是 %d
    ",a[1]);
    
        //通过指针访问数组元素
        printf("通过指针方式:第2个元素是 %d
    ",*(p+1));
    
    
    }
    

      分析:

    (1)数组名a做右值时表示数组首元素的首地址,当p = a后,p也保存了数组首元素的首地址,当p+1时,p+1就指向了数组的第二个元素的首地址,以此类推。这里注意一点,p只是保留了首地址(一个字节),而第一个元素是int类型,占4个字节,这时候就靠指针p的数据类型的作用了,一看p是int*类型的指针,自动会根据p保留的第一个字节的地址去补齐剩下的那3个字节的地址,当找到4个字节地址后再去读取该值。

    (1.1)比如 int a[5];int * p = a;当p自增1时,其实是自增(1+sizeof(指针类型)),举例:当int * p;p实际上是自增4个字节,char * p;p实际上是自增1个字节。

    (1.2)指针在进行运算的时候,指针自增多少关键看指针类型。这时候再来看&a和a。&a做右值是数组指针,当&a自增时,实际上是增加了一个数组sizeof(int) * 5= 20个字节。而 a 自增实际上是自增了一个sizeof(int)大小的字节。

    (3)看上面的代码,int * p = a; 若是改成int* p=&a;会怎样?一步一步分析:&a做右值时,代表数组的首地址,其数据类型是int (*)[5],这就得出了结果,&a和p类型不符,编译器报错。

    (4)再来回顾一下,数组元素地址是连续的。所以指针访问数组才能自增去寻址。

    总结
    (1)a,a[0],&a,&a[0],做左值和做右值的区别
    (2)指针自增的含义
    (3)指针类型的含义
    (4)数组和指针的相似处

    下次说说指针和类型转换的内容

  • 相关阅读:
    C语言面向对象编程(五):单链表实现(转)
    pthread_barrier_init,pthread_barrier_wait简介(转)
    Linux信号(signal) 机制分析(转)
    Linux 进程间通信 --- 信号通信 --- signal --- signal(SIGINT, my_func); --- 按键驱动异步通知(转)
    Linux 多线程环境下 进程线程终止函数小结(转)
    批量杀进程 ps awk grep
    C++中的INL(转)
    gdb调试多进程和多线程命令(转)
    转: 基于netty+ protobuf +spring + hibernate + jgroups开发的游戏服务端
    转:全栈工程师的知识栈列表
  • 原文地址:https://www.cnblogs.com/1024E/p/13209625.html
Copyright © 2011-2022 走看看