• 第27课 数组的本质分析


    1. 数组的概念

    (1)数组相同类型的变量有序集合

        

    (2)数组一片连续的内存空间中存储元素

    (3)数组元素个数可以显示或隐式指定

    【编程实验】数组的初始化

     1 #include <stdio.h>
     2 
     3  
     4 
     5 int main(){
     6 
     7  
     8 
     9     //数组初始化
    10 
    11     int a[5] = {1, 2};//第1、2个元素分别为1、2,其余为0
    12 
    13     int b[]  = {1, 2};//编译过程中,编译会为计算数组b的大小
    14 
    15    
    16 
    17     int i=0;
    18 
    19     for (i = 0;i < 4;i++)
    20 
    21     {
    22 
    23         printf("a[%d] = %d
    ",i,a[i]);
    24 
    25     }
    26 
    27  
    28 
    29     printf("sizeof(a) = %d
    ",sizeof(a));  //20
    30 
    31     printf("sizeof(b) = %d
    ",sizeof(b));  //8
    32 
    33    
    34 
    35     printf("count for a: %d
    ",sizeof(a)/sizeof(int));  //5
    36 
    37     printf("count for b: %d
    ",sizeof(b)/sizeof(int));  //2
    38 
    39  
    40 
    41     return 0;
    42 
    43 }

    2. 数组地址(&a)数组名a

    (1)数组名a代表数组首元素的地址。因此,第2个元素的地址为a+1,以此类推……。注意a或a+i表示元素的地址。可以用*(a+i)取出元素的值,也可以用a[i]来取出元素的值,因为当编译中遇到a[i]会自动转为*(a+i)。反过来也可知,第1个元素的地址为a或&a[0],第2个元素的地址为a+1或&a[1],第i个元素的地址为(a+i)或&a[i]……

    (2)数组的地址需要用取地址符&才能得到。即形如&a取的是整个数组的地址,所以&a+1表示指向整个数组的最后面的位置

    (3)数组的首元素的地址值数组的地址值相同,但是两个不同的概念

    【编程实验】数组名和数组地址

     1  
     2 #include <stdio.h>
     3 
     4  
     5 
     6 int main(){
     7 
     8    
     9 
    10     //将数组每个元素初始化为0
    11 
    12     int a[5] = {0};//含义,将第1个元素初始化为0,其余为0.
    13 
    14    
    15 
    16     printf("a = %p
    ",a); //首元素的地址
    17 
    18     printf("&a = %p
    ",&a); //整个数组的地址,从数值与看,与a一样。
    19 
    20     printf("&a[0] = %p
    ",&a[0]);//第1个元素的地址
    21 
    22  
    23 
    24     return 0;
    25 
    26 }

    3. 数组名的盲点

    (1)数组名内涵在于其指代实体是一种数据结构这种数据结构就是数组。如int a[5]表示a的类型为int[5],所以sizeof(a)表示取整个数组的大小,&a表示数组的地址。

    (2)数组名外延:除了sizeof(a)和&a外数组名经常可看作是一个常量指针。但要注意这里仅仅是“看作”,而不是真正的指针。不同于指针,数组名只是编译过程中的一个符号编译器并不为其分配内存,有人称之为伪变量。因此,形式a++a—或a=b(其中b是另一个数组名)这些都是错误的,因为a只是一个符号,编译器会把数组信息(如大小,地址)放入符号表中,每次遇到数组名a时,就会从符号表中取出这个数组的地址,然后用这个固定的地址代替 a,所以这个符号并没有被分配内存空间,而上述操作都是针对变量而言的,故数组名只能做为右值使用

    (3)对数组的引用,如a[i]或*(a+i),只需访问内存一次,而指针的引用如*(p+i)则需要两次,首选通过&p找到p指针,然后加i,再从p+i里面取出的内容。

    (4)数组名作为形参时,将退化为指针即可以把数组名当成指针来用,这里的sizeof(数组名)为4,即指针的长度

    【实例分析】数组和指针并不相同

     1 #include <stdio.h>
     2 
     3  
     4 
     5 int main(){
     6 
     7    
     8 
     9     //将数组每个元素初始化为0
    10 
    11     int a[5] = {0};
    12 
    13     int b[2];
    14 
    15     int* p = NULL;
    16 
    17  
    18 
    19     p = a;
    20 
    21  
    22 
    23     printf("a = %p
    ",a);  //首元素的地址
    24 
    25     printf("p = %p
    ",p);  //p==a。
    26 
    27     printf("&p = %p
    ",&p);//指针p的地址
    28 
    29  
    30 
    31     printf("sizeof(a) = %d
    ",sizeof(a));//数组的大小:20
    32 
    33     printf("sizeof(p) = %d
    ",sizeof(p));//指针的大小为4.
    34 
    35  
    36 
    37     printf("
    ");
    38 
    39    
    40 
    41     p = b;
    42 
    43  
    44 
    45     printf("b = %p
    ",b);  //首元素的地址
    46 
    47     printf("p = %p
    ",p);  //p==b。
    48 
    49     printf("&p = %p
    ",&p);//指针p的地址
    50 
    51  
    52 
    53     printf("sizeof(b) = %d
    ",sizeof(b));//数组的大小:8
    54 
    55     printf("sizeof(p) = %d
    ",sizeof(p));//指针的大小为4.
    56 
    57  
    58 
    59     //a = b; //编译错误,数组名不能作为左值;
    60 
    61     //a++;   //编译错误,数组名被编译一个固定地址,相当于0xaabbccdd++的错误
    62 
    63     return 0;
    64 
    65 }

    4. 小结

    (1)数组一片连续的内存空间

    (2)数组的地址数组首元素的地址意义不同

    (3)数组名大多数情况下被当成常量指针处理

    (4)数组名其实并不是指针,不能将其等同于指针。

  • 相关阅读:
    lms框架服务注册中心
    lms框架应用服务接口和服务条目详解
    lms框架模块详解
    lms微服务框架主机介绍
    lms框架分布式事务使用简介
    MySQL锁总结
    VSCode 输出 java SSL 请求过程
    PowerShell自动化发布SpringBoot项目到Tomcat
    AWS EC2 使用---安装Docker和Nginx
    使用PowerShell连接到Linux
  • 原文地址:https://www.cnblogs.com/hoiday/p/10056111.html
Copyright © 2020-2023  润新知