• C和指针 第八章 数组


    8.1 数组名和指针  

    int a;
    int b[10];
    

     a称为一个标量,表示一个单一的值,变量的类型是整数。

     b是数组,b[1]的类型是整数,b是一个指针常量,表示数组第一个元素的地址。b的类型取决于数组的类型,在这里b是指向int的常量指针,如果是其他类型的数组,那么就是指向其他类型的指针常量

     但是数组和指针并不相同,数组是有确定数量的元素,而指针只是一个标量,编译器有数组名来记住这些属性,当数组名在表达式中使用时,编译器才会为他产生一个指针常量。数组名是指针常量,所以是不可以修改的,他指向内存中数组的起始位置,第一个元素的位置。

      只有在两种场合下,数组名并不用指针常量来表示:

      数组名当做sizeof操作数时返回数组的长度

      &操作符,取一个数组名的地址,所产生的是一个指向数组的指针,而不是指向指针的指针

      如下:

    #include <stdio.h>
    
    int main()
    {
        int a[10] = {};
    
        printf("%lu
    ", sizeof a);
        return 0;
    }
    

      输出40,sizeof的返回值是long unsigned int。

    #include <stdio.h>
    
    int main()
    {
        int a[3] = {1, 2, 3};
        int b[3] = {4, 5, 6};
        int *c;
    
        //&a[0]指向第一个元素的指针,合法
        c = &a[0];
    
        //b为常量所以不合法,指针的复制应该通过循环来进行复制
        b = a;
        printf("%lu
    ", sizeof a);
        return 0;
    }
    

      8.1.2 下标

    在之前的上下文环境中,

    *(b + 3)
    

    首先,b指向数组的第一个元素的指针常量,这里加上3个整数长度,如果是float类型的数组,会加上三个float类型的长度,这里所加的长度是取决于数组的类型,然后间接访问这个新位置。除了优先级之外和下标访问完全相同。等价与

    b[3]
    

    所以对于下面的表达式也是合法的:

    3[b];
    

    转换成指针间接访问表达式:

    *(3 + b);
    

    由于编译器实现下标的方法,所以这两种形式并无差别。

    8.19 初始化

    #include <stdio.h>
    
    int main()
    {
        //非法,不可以把4个数放到三个位置里面
        int a[3] = {1, 2, 3, 4};
        //合法,缺省的值为0,实际上b是 [0, 0, 0]数组
        int b[3] = {};
       	
        return 0;
    }
    

      如果声明中为给出数组的长度,编译器就把数组的长度设置为,刚刚好能够容纳初始元素的值的长度。

    //a的长度为4
    int a[] = {1, 2, 3, 4};
    

      字符数组初始化,

    #include <stdio.h>
    
    int main()
    {
    	//下面这两种方式都是字符数组初始化,注意第二个不是字符串常量的初始化
    	char message1[] = {'m', 'e' , 's', 's', 'a', 'g', 'e', ''};   
    	char message2[] = "message";
    	//下面是字符串常量的初始化
    	char *message3 = "message";
    
            printf("%s
    ", message2);
            return 0;
    }
    

      当初始化一个数组时,字符串常量初始化的是一个字符串列表,其他地方是字符串常量。

      多维数组:

      多维数组是指数组内的元素也是数组的数组,例如

    int matrix[10][6];
    

      对于matrix,它有十个元素,其中的每个元素是一个长度为6的数组。同时,matrix是指向数组第一个元素的指针,这里matrix是指向有6个整数的数组的指针,matrix的类型为

    int (*p)[6] = matrix;
    

    此时,对面matrix的增量运算

    *(matrix + 1);
    

      数组名的运算所加的长度取决于数组的元素的类型,这里数组内元素是有6个整数的数组。所以matrix  + 1,移动了6 个整数长度的位置。matrix + 1指向数组第二行,

    #include <stdio.h>
    
    int main()
    {
    
    	int matrix[10][6] = {};
    	//[]优先级较高,所以要加()
    	int (*matrix2)[6] = matrix + 1;
    	//*matrix2和*matrix分别指向数组第一行数组的第一个值,和第二行数组的第一个值
    	printf("%lu
    ", *matrix2 - *matrix);
    
        return 0;
    }
    

      输出6,位置相差6个int的长度。

      当需要在多维数组上进行指针运算时,需要指定每个数组元素的长度。

    #include <stdio.h>
    
    int main()
    {
    
    	int matrix[10][6] = {};
    	//此时进行运算,讲根据空数组的长度进行调整,与零相乘
    	int (*p)[] = matrix;
    	//正确的声明应该加上多维数组的长度,这样编译器就可以进行下标运算
    	int (*p)[6] = matrix;
    
        return 0;
    }
    

      同样,多维数组的声明时,需要自动计算长度也要指定多维的长度。

    //只有matrix[0][0]被声明为1,其他均为0
    int matrix[][6] = {
    	{1},
    };
    

      指针数组:

    #include <stdio.h>
    
    int main()
    {
    	//指针数组,keyword1数组内都是指针。
    	char const *keyword1[] = {"name", "age"};
    	//字符矩阵,keyword2数组内都是长度为10的字符数组。
    	char const keyword2[][10] = {"name", "age"};
    
    	printf("%lu
    ", sizeof keyword1[1]);
    	printf("%lu
    ", sizeof keyword2[1]);
    
        return 0;
    }
    

      输出:8 和 10。8是指针的大小,10是keyword2中每个矩阵的大小。

  • 相关阅读:
    [转] CSocket 和CAsyncSocket类介绍
    error C2275: 'SOCKET' : illegal use of this type as an expression
    tagVARIANT、VARIANT、_variant_t和COleVariant
    使用MFC WinInet进行FTP中文件的简单上传和下载功能
    【转】VS2008快速将代码中字符串改为_T(“”)风格的方法
    【转】Internet与Intranet区别
    POSIX是什么?
    Ocx控件注册不成功?可能是tlb文件导致~
    十三种基于直方图的图像全局二值化算法原理、实现、代码及效果(转)
    图像匹配之欧式距离算法(转)
  • 原文地址:https://www.cnblogs.com/yangxunwu1992/p/5801235.html
Copyright © 2020-2023  润新知