• C Primer Plus(6) 中文版 第10章 数组和指针 10.9 复合字面值 10.10 关键概念 10.11 本章小结


    10.9 复合字面值
    在C99标准以前,对于带数组形参的函数,情况不同,可以传递数组,但是没有等价的数组常量。C99新增了复合字面值(compound literal)。
    字面量是除符号常量外的常量。例如,'Y'是char类型的字面量。发布C99标准的委员会认为,如果有代表数组和结构内容的复合字面量,在编程时会更方便。
    对于数组,复合字面值类似数组初始化列表,前面使用括号括起来的类型名。例如下面的普通数组的声明:
    int div[2] = {10, 20};
    下面的复合字面值创建了一个和diva数组相同的匿名数组,也有两个int类型的值:
    (int [2]){10, 20}  //复合字面量
    注意,去掉声明中的数组名,留下的int [2]即是复合字面量的类型名。
    初始化有数组名的数组时可以省略数组大小,复合字面量也可以省略大小,编译器会自动计算数组当前的元素个数:
    (int []){50,20,90} //内含3个元素的复合字面量
    因为复合字面量是匿名的,所以不能先创建然后再使用它,必须在创建的同时使用它。使用指针记录地址就是一种用法。也就是说,可以这样用:
    int *pt1;
    pt1 = (int [2]){10, 20};
    注意,该复合字面量的字面常量与上面创建的diva数组的字面常量完全相同。与有数组名的数组类似,复合字面量的类型名也代表首元素的地址,所以可以把它赋给指向int的指针。然后便可以使用这个指针。
    还可以把复合字面量作为实际参数传递给带有匹配形式参数的函数:
    int sum( const int ar[], int n );
    ...
    int total3;
    total3 = sum( (int []){4, 4, 4, 5, 5, 5}, 6 );
    这里,第1个实参是内含6个int类型值的数组,和数组名类似,这同时也是该数组首元素的地址。这种用法的好处是,把信息传入函数前不必先创建数组,这是复合字面量的典型用法。
    可以把这种用法应用于二维数组或多维数组。例如:
    如何创建二维int数组并存储其地址:
    int (*pt2)[4];  //声明一个指向二维数组的指针,该数组内含2个数组元素
                        //每个元素都是内含4个int类型值的数组
    pt2 = (int [2][4]){ {1, 2, 3, -9}, {4, 5, 6, -8} };
    如上所示,该复合字面量的类型是int[2][4],即一个2*4的int数组。
    // flc.c -- funny-looking constants
    #include
    #define COLS 4
    int sum2d(const int ar[][COLS], int rows);
    int sum(const int ar[], int n);
    int main(void)
    {
        int total1, total2, total3;
        int * pt1;
       int (*pt2)[COLS];
        
        pt1 = (int [2]) {10, 20};
        pt2 = (int [2][COLS]) { {1,2,3,-9}, {4,5,6,-8} };
        
        total1 = sum(pt1, 2);
        total2 = sum2d(pt2, 2);
        total3 = sum((int []){4,4,4,5,5,5}, 6);
        printf("total1 = %d\n", total1);
        printf("total2 = %d\n", total2);
        printf("total3 = %d\n", total3);
        
        return 0;
    }

     

    int sum(const int ar[], int n)
    {
        int i;
        int total = 0;
        
        for( i = 0; i < n; i++)
            total += ar[i];
        
        return total;
    }

    int sum2d(const int ar[][COLS], int rows)
    {
        int r;
        int c;
        int tot = 0;
        
        for (r = 0; r < rows; r++)
            for (c = 0; c < COLS; c++)
                tot += ar[r][c];
        
        return tot;
    }

    /* 输出:

     */

    显示类型不兼容,把int (*pt2)[COLS];修改为const int (*pt)[COLS];和pt2 = (int [2][COLS]) { {1,2,3,-9}, {4,5,6,-8} };修改为pt2 = (const int [2][COLS]) { {1,2,3,-9}, {4,5,6,-8} };则会去掉警告,并且结果也运行正确。 

    有没有大神知道const int (*)[4]和int (*)[4]为什么不兼容吗?知道的麻烦评论一下!!! 

    要支持C99的编译器才能正常运行该程序示例。
    记住,复合字面值是提供只临时需要的值的一种手段。复合字面量具有块作用域,这意味着一旦离开定义复合字面量的块,程序将无法
    保证该字面量是否存在。也就是说,复合字面量的定义在最内层的花括号中。 

    10.10 关键概念
    C把数组看作是派生类型,因为数组是建立在其他类型的基础上。也就是说,无法简单地声明一个数组。在声明数组时必须说明其元素的类型。元素的类型也可以是数组类型,在这种情况下,创建的是数组的数组(或称为二维数组)。
    C99/C11新增了变长数组,可以用变量表示数组大小。这意味着变长数组的大小延迟到程序运行时才确定。

    10.11 本章小结
    声明一个简单的一维数组形式如下:
    type name[ size ];
    如果ar是一个数组,那么表达表达式ar[i]和*(ar + i)等价。
    字符串有一些特殊的规则,这是由于其末尾的空字符所致。有了这个空字符,不用传递数组的大小,函数通过检查字符串的末尾也知道在何处停止。

  • 相关阅读:
    代码随想录算法训练营第四十一天 | 01背包问题 二维
    【Mysql】Mysql内置函数介绍
    java中的异常处理分析
    第22章_数据库的设计规范
    高德地图,绘制矢量图形并获取经纬度
    C# WPF 开发一个 Emoji 表情查看软件
    【HBZ分享】TCP可靠性传输如何保证的?以及传输优化之Nagle算法
    Redis数据类型之Set的使用
    【PDF技巧】网上下载的pdf文件怎么才能编辑
    国际版Amazon Lightsail的功能解析
  • 原文地址:https://blog.csdn.net/weixin_40186813/article/details/126259618