zoukankan      html  css  js  c++  java
  • 数组

    一维数组

    一维数组初始化

    • 在创建数组时,我们必须定义数组的类型和大小,数组的大小不能为0,数组中的元素类型都是相同的。
    • 数组长度必须是固定的,必须为常量或常量表达式,不能使用变量进行初始化。

    一维数组初始化

    • 完整初始化:int arr[3] = {1, 2, 3};
    • 不完整初始化:int arr[3] = {1, 2};
    • 自动计算数组长度初始化:int arr[] = {1, 2, 3};

    注意:

    • 静态初始化缺省情况将数组元素自动设置为0,自动初始化缺省情况下是未初始化的。
    • 数组初始化元素的个数不允许超过数组长度:int a[3] = {1,2,3,4}; // 不合法

    字符数组的初始化

    • 最笨拙的方式:char message[] = { 'h','e','l','l','o',0 };

    • 快速初始化方式:char message[] = "hello";这种初始化方式与上面的初始化方式是等效的,并且默认会在末尾''

    • 上面都是字符数组初始化的基本方式,如果要初始化字符串常量,则采用:char *message = "hello";

      初始化字符数组和字符串常量的区别,可以表示如下:

    作符返回一个指向数组的指针,而不是一个指向数组第一个元素的指针的指针。

    注意:

    • 数组名的值是一个指针常量,不能修改它的值。

      int a[5];
      int b[5];
      a = b; // 操作违法,数组名是指针常量,不能改变它的值
      

    一维数组的访问

    • 一维数组是使用下标来访问的,下标从0开始。
    • 数组的大小通过计算可以得到: sz=sizeof(arr)/sizeof(arr[0]);
    • 一维数组还可以通过指针来访问。
    int array[10];
    int *ap = array + 2;
    
    表达式 含义
    ap 与之对等的表达式是&array[2]
    *apy 与之对等的表达式是array[2]
    ap[0] c的下标引用和间接表达式是一致的,此处可以理解为*[ap+(0)],也就是*ap,即array[2]
    ap+6 与之对等的表达式是&array[8],或者array+8
    *ap+6 与之对等的表达式是array[2]+6
    *(ap+6) 与之对等的表达式是array[8]
    ap[6] 与之对等的表达式是array[8]
    &ap 表达式是合法的,但是找到与之对等的表达式,因为无法知道编译器将ap放在相对于array的什么位置
    ap[-1] 与之对等的表达式是array[1]
    ap[9] 这个表达式是非法的,访问越界

    考虑下面的表达式

    2[array]
    

    这个表达式是合法的,将其转换成对等的间接访问表达式为*(array+2),也就是array[2]。但是为了程序的可读性,强烈不建议如此写法。

    一维数组和指针

    int a[5];
    int *b;
    

    声明一个数组时,编译器先根据指定的元素数量为数组保存内存空间,然后创建数组名,它的值是一个常量,指向这段空间的起始位置。

    声明指针的时候,编译器只为指针本身保留内存空间,并且指针变量并没有被初始化指向任何的内存空间。

    下两个声明都是正确的:

    int    strlen (char *string );
    int    strlen( char string[]);
    

    如果函数需要知道数组的长度,那么它必须作为一个显示的形参传递给函数。

    多维数组

    当数组维数不止一个时,我们可以声明多维数组。

    多维数组的存储顺序

    int a[3][6]内存中的存储顺序为:

    看作一个初始化列表。

    数组长度自动计算

    int array[][5] = {
    {0,1,2,3},
    {4,}
    {5,6}
    }
    

    对于上面的多维数组定义,编译器能够自动推断出数组的第一个维度是3。

    多维数组的数组名

    多维数组的数组名也是个指针常量,但是和一维数组不同,多维数组的数组名是指向数组第一行的常量指针,而不是指向第一个元素。

    int matrix[3][10];
    

    matrix可以看作一个一维数组,包含3个元素,每个元素都是包含10个整型数的数组。

    多维数组的下标

    假设声明了int matrix[3][10];

    表达式 含义
    matrix[1][5] 表示数组的第二行第六个元素
    matrix 指向数组的第一行,它的类型:指向包含10个整型元素的数组的指针
    matrix+1 指向数组的第二行,它的类型:指向包含10个整型元素的数组的指针
    *(matrix+1) 指向数组的第二行第一个元素的值,即&matrix[1][0],它的类型是:int*
    *(matrix+1)+5 指向数组的第二行第六个元素的值,即&matrix[1][5],它的类型是:int*
    *(*(matrix+1)+5) 取右值,即a[1][5]

    指向多维数组的指针

    int    a1[10],   	 *p1=a1;
    int    a2[3][10],    *p2=a2;
    

    第一个声明是正确的,第二个声明是不正确的,因为a2的类型不是 int*而是int (*p)[10]

    所以上面的表达式应该更改为:

    int a2[3][10];
    int (*p2)[10] = a2;
    
    

    它使p2指向a2的第一行。下面的两个声明都是使p2指向a2的第一个整型元素:

    int *p2 = &a2[0][0]
    int *p2 = &a2[0];
    
    

    作为函数参数的多维数组

    作为函数参数的多为数组名的传递方式和一维数组相同——实际传递的是数组的第一个元素。两者的区别是,多位数组的每个元素本身是一个数组,所以以下声明:

    int    arr[3][10];
    ...
    fun(arr);
    
    

    参数arr的类型是指向包含十个整形元素的数组的指针。fun的原型为如下两种形式中的任何一种:

    void    fun(int     (*arr)[10]);
    void    fun(int     arr[][10]);
    
    

    指针数组

    int    *api[10];
    
    

    因为下标引用的优先级高于间接访问,所以表达式先执行下标操作,所以api是某种类型的数组。对数组的某个元素执行间接访问操作后,得到一个整型,所以api的元素类型为指向整型的指针。

    指针数组的应用,例如分析C语言中关键字的个数:

    char const *keyword[] = {
        "do",
        "for",
        "if",
        "register",
        "return",
        "switch",
        "while"
    };
    
    #define N_KEYWOLD 
    	(sizeof(keyword)/sizeof(keyword[0]))
    
    

    存储结构:

    如果使用矩阵存储关键字:

    char const keyword[][9] = {
    	"do",
    	"for",
    	"if",
    	"register",
    	"return",
    	"switch",
    	"while"
    };
    

    此时的存储结构:

    两种形式存储结构的比较:

    • 如果存储的字符串长度差不多,那么采用矩阵形式更加紧凑。
    • 如果字符串长度千差万别,并且大多数很短,极少数很长,此时使用指针数组的形式将更加紧凑。
  • 相关阅读:
    按字母分类的产品组件
    container中的内容 垂直-水平居中
    安卓手机--键盘谈起后 fixed背景图片被键盘顶起的问题
    清除样式的css
    vue 路由(二级)配置及详细步骤
    vue 路由 URL传参
    路由表的组件群
    vue 路由传参
    vue 路由入门(vue-router)
    jQuery对文档的操作
  • 原文地址:https://www.cnblogs.com/chay/p/11521350.html
Copyright © 2011-2022 走看看