精华内容
下载资源
问答
  • 复合字面量
    2021-11-17 15:46:57

    假设给带 int 类型形参的函数传递一个值,可以传递 int 类型的变量,或者是 int 类型的常量,例如 620

    对于带数组形参的函数,可以传递数组,在 C99 之后,也可以传递代表数组和结构内容的复合字面量

    (int []) {18, 19, 22, 23, 24} // 内含 5 个元素的字面量
    

    注意:因为复合字面量是匿名的,所以必须在创建的同时使用它。使用方法和正常创建的数组完全相同

    int * p = (int []) {18, 19, 22, 23, 24};
    
    // p = 000000000061FE00, p + 1 = 000000000061FE04
    printf("p = %p, p + 1 = %p\n", p, p + 1);
    

    将复合字面量作为实参传递给带有匹配形式的函数

    int sum(const int ar[], int n);
    
    int total = sum((int []) {18, 19, 22, 23, 24}, 5);
    

    应用于多维数组

    int (* p)[2] = (int [][2]) { {18, 19}, {22, 23}};
    
    // **p = 18, **p + 1 = 19
    printf("**p = %d, **p + 1 = %d\n", **p, **p + 1);
    

    注意:复合字面量是提供只临时需要的值的一种手段。复合字面量具有块作用域,这意味着一旦离开定义复合字面量的块,程序将无法保证该字面量是否存在。也就是说,复合字面量的定义在最内层的花括号中

    更多相关内容
  • 关注、星标公众号,直达精彩内容来源:技术让梦想更伟大作者:李肖遥C语言中有没有见过(int [2]){19,20}或者int (*pt2)[4]的使用方法,字面上可能不好理解,这是C99之...

    关注、星标公众号,直达精彩内容

    来源:技术让梦想更伟大

    作者:李肖遥

    C语言中有没有见过(int [2]){19,20}或者int (*pt2)[4]的使用方法,字面上可能不好理解,这是C99之后才新增的知识点,名为复合字面量(Compound Literals),一旦熟悉使用,便会体会到它简洁而强大的表达。

    什么是复合字面量?

    假设给带int类型的形参函数传递一个值,可以传递int类型的变量,也可以传递int类型常量,但是对于带数组形参的函数则不一样,可以传递数组,但是不支持传递数组常量,由此C99新增了复合字面量的用法,字面量是指除符号常量外的常量。

    例如10是int的类型的字面量,10.24是double类型的字面量,“lixiaoyao”是字符串的字面量等,如果有数组或者结构体的字面量,这样使用起来会更方便。

    对于数组

    数组的复合字面量和数组初始化列表差不多,前面使用括号括起来的类型名,例如下面是一个普通的数组声明。

    int age[2]=[19,20];

    <
    展开全文
  • 因此,C99标准委员会就新增了复合字面量(compound literals)。 文章目录定义语法约束语义用法文件作用域的匿名数组函数作用域的匿名数组同一函数作用域的单例复合字面量"对象" 定义 语法 ( type-name ) { ...

    字面量是除了符号常量之外的常量。如,1是int型字面量,3.14是float型字面量,'C’是char型字面量,'Yudao’是字符串字面量。那么,数组和结构体是否也能有字面量来表示呢?如定义了这种"字面量",能带来什么好处呢(后文中逐一介绍)? 因此,C99标准委员会就新增了复合字面量(compound literals)

    定义

    语法

    ( type-name ) { initializer-list }

    ( type-name ) { initializer-list , }

    约束

    1. The type name shall specify an object type or an array of unknown size, but not a variable length array type.

    type name指定了数组类型或结构体类型,数组长度不能是可变的。

    1. No initializer shall attempt to provide a value for an object not contained within the entire unnamed object specified by the compound literal.

    匿名"对象"的初始化必须在在复合字面量的大括号中。

    1. If the compound literal occurs outside the body of a function, the initializer list shall consist of constant expressions.

    如果复合字面量是文件作用域,initializer list的表达式必须是常量表达式。

    语义

    1. A postfix expression that consists of a parenthesized type name followed by a brace enclosed list of initializers is a compound literal. It provides an unnamed object whose value is given by the initializer list.

      一个由( type-name ) { initializer-list }构成的后缀表达式就是复合字面量,它定义了一个匿名"对象",该"对象"的值由initializer list指定。

    2. If the type name specifies an array of unknown size, the size is determined by the initializer list as specified in 6.7.8, and the type of the compound literal is that of the completed array type. Otherwise (when the type name specifies an object type), the type of the compound literal is that specified by the type name. In either case, the result is an lvalue.

      如果type name是一个匿名数组,那么该数组的长度由initializer list的元素个数决定。复合字面量可以作为左值。

    3. The value of the compound literal is that of an unnamed object initialized by the initializer list. If the compound literal occurs outside the body of a function, the object has static storage duration; otherwise, it has automatic storage duration associated with the enclosing block.

      复合字面量的值是由initializer list指定。如果复合字面量是文件作用域,该"对象"是static storage duration;如果复合字面量是函数作用域或块作用域,该"对象"是automatic storage duration。

    4. All the semantic rules and constraints for initializer lists in 6.7.8 are applicable to
      compound literals.

    用法

    文件作用域的匿名数组

    #include <stdio.h>
    #include <stdlib.h>
    
    int *p = (int[]){1, 2, 3};
    int *p2 = (int[]){1, 2, 3};
    
    int main(int argc, char** argv)
    {
       	printf("p=%p\n", p);
    	printf("p2=%p\n", p2); 
        
        return 0;
    }
    
    // 运行结果为
    // p=0x55764bdc4010
    // p2=0x55764bdc4020
    

    文件作用域(file scope)定义复合字面量,initializer-list中的表达式必须为常量。文件作用域的复合字面量,具有static storage duration,存储在.data section

    在这里插入图片描述

    在这里插入图片描述

    函数作用域的匿名数组

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char** argv)
    {
    
        int a[32] = {4,5,6};
        int *p = (int[]){1, 2, 3};
    
        printf("&a[0]=%p\n", &a[0]);
        printf("p=%p\n", p);
    
        return 0;
    }
    
    // 运行结果
    // &a[0]=0x7ffff11d2fb0
    // p=0x7ffff11d2fa4
    

    函数作用域的复合字面量,具有automatic storage duration,从打印的地址可以知道,匿名数组存储在栈上。(栈特点:向低地址方向增长)

    
    "/tmp/fileXXXXXX"	// static storage duration;数组类型为char;数组内容不能修改
    (char []){"/tmp/fileXXXXXX"} // 在函数作用域内时,automatic storage duration,该匿名数组的内容可以修改
    (const char []){"/tmp/fileXXXXXX"} // 在函数作用域内时,automatic storage duration,因为有const修饰,该匿名数组的内容不可以修改
    
    // 与字符串字面量(如,"abc")类似,const修饰的复合字面量也可是read-only memory和can even be shared
    (const char []){"abc"} == "abc"
    // 如果字面量的storage是shared,该表达式为真。
    // storage is shared该怎么理解?
    

    同一函数作用域的单例复合字面量"对象"

    为了讲清楚什么是 单例 复合字面量"对象",先看如下代码

    #include <stdio.h>
    #include <stdlib.h>
    
    struct s { int i; };
    
    // 函数f的返回值总是为1
    int f (void)
    {
        struct s *p = 0, *q;
        int j = 0;
    
    again:
        q = p, p = &((struct s){ j++ });
        printf("p=%p\n", p);
        if (j < 2) goto again;
    
        return p == q && q->i == 1;
    }
    
    // 函数f2的返回值也总是为1
    int f2 (void)
    {
        struct s *p = 0, *q;
        int j = 0;
    
        while(j < 2)
        {
            q = p, p = &((struct s){ j++ });
            printf("p=%p\n", p);
        }
    
        return p == q && q->i == 1;
    }
    
    int main(int argc, char** argv)
    {
        printf("f() return:%d\n", f());
        printf("f() return:%d\n", f());
        printf("f() return:%d\n", f());
    
        printf("f2() return:%d\n", f2());
        printf("f2() return:%d\n", f2());
        printf("f2() return:%d\n", f2());
    
        return 0;
    }
    

    看一下,运行结果:

    p=0x7fff543fa7f0
    p=0x7fff543fa7f0
    f() return:1
    p=0x7fff543fa7f0
    p=0x7fff543fa7f0
    f() return:1
    p=0x7fff543fa7f0
    p=0x7fff543fa7f0
    f() return:1
    p=0x7fff543fa7f0
    p=0x7fff543fa7f0
    f2() return:1
    p=0x7fff543fa7f0
    p=0x7fff543fa7f0
    f2() return:1
    p=0x7fff543fa7f0
    p=0x7fff543fa7f0
    f2() return:1
    

    从打印结果可以看出,函数f和函数f2中的指针p指向的匿名对象的地址都相同。

    函数f的作用域内,复合字面量"对象"是单例;

    函数f2中,虽然匿名对象的地址也相同,但由于有while的块作用域,不一定匿名对象是单例,也可能恰好第一次循环分配的匿名对象释放了,然后第二次循环又在相同的地址上分配该匿名对象。

    在C99标准中有这样一段话:

    Each compound literal creates only a single object in a given scope.

    Note that if an iteration statement were used instead of an explicit goto and a labeled statement, the lifetime of the unnamed object would be the body of the loop only, and on entry next time around p would have an indeterminate value, which would result in undefined behavior.

    我暂时没有找到详细关于这段话的解释,只能通过实际的测试来验证,可能我上述的结论不一定正确。

    接下来,看一个实际工程中使用复合字面量的例子

    #include <stdint.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define MKTAG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((unsigned)(d) << 24))
    
    #define AV_FOURCC_MAX_STRING_SIZE 32
    #define av_fourcc2str(fourcc) av_fourcc_make_string((char[AV_FOURCC_MAX_STRING_SIZE]){0}, fourcc)
    
    char *av_fourcc_make_string(char *buf, uint32_t fourcc)
    {
        int i;
        char *orig_buf = buf;
        size_t buf_size = AV_FOURCC_MAX_STRING_SIZE;
    
        for (i = 0; i < 4; i++) {
            const int c = fourcc & 0xff;
            const int print_chr = (c >= '0' && c <= '9') ||
                                  (c >= 'a' && c <= 'z') ||
                                  (c >= 'A' && c <= 'Z') ||
                                  (c && strchr(". -_", c));
            const int len = snprintf(buf, buf_size, print_chr ? "%c" : "[%d]", c);
            if (len < 0)
                break;
            buf += len;
            buf_size = buf_size > len ? buf_size - len : 0;
            fourcc >>= 8;
        }
    
        return orig_buf;
    }
    
    int main(int argc, char** argv)
    {
        uint32_t type = MKTAG('r', 'o', 'o', 't');
        printf("%s\n", av_fourcc2str(type));
        return 0;
    }
    

    av_fourcc2str宏的作用是将以整型存储的4字符转换为字符串,其中使用了(char[AV_FOURCC_MAX_STRING_SIZE]){0},使代码更加的简洁。

    展开全文
  • 复合字面量

    2020-09-24 14:48:43
    C99新增了复合字面量(compound literal)。字面量是除符号常量外的常量。例如,5是int类型字面量,81.3是double类型的字面量,'Y’是char类型的字面量,"elephant"是字符串字面量。 对于数组,复合字面量类似数组...

    给带int形参的函数传递一个值,可以传递一个int类型的变量,也可以是一个in类型的常量,例如5。
    对于带数组形参的函数,在C99标准以前,可以传递数组,但没有等价的数组常量。
    C99新增了复合字面量(compound literal)。字面量是除符号常量外的常量。例如,5是int类型字面量,81.3是double类型的字面量,'Y’是char类型的字面量,"elephant"是字符串字面量。
    对于数组,复合字面量类似数组初始化,前面是用括号括起来的类型名。
    例如,下面是个普通的数组声明:

    int diva[2]=[10.20]; //声明数组
    

    下面的复合字面量创建了一个与diva数组相同的匿名数组:

    (int [2]){10,20};  //复合字面量
    

    注意,去掉声明中的数组名,留下的int [2]即是复合字面量的类型名。
    初始化有数组名的数组时可以省略数组大小,复合字面量也可以省略大小,编译器会自动计算数组当前的元素个数:

    (int []){50, 20, 90} // 内含3个元素的复合字面量
    

    使用复合字面量

    因为复合字面量是匿名的,所以不能先创建然后再使用它,必须在创建的同时使用它。
    使用指针记录地址就是一种用法。也就是说,可以这样用:

    int * pt1;
    pt1 = (int [2]) {10, 20};
    

    注意,该复合字面量的字面常量与上面创建的 diva 数组的字面常量完全相同。与有数组名的数组类似,**复合字面量的类型名也代表首元素的地址,所以可以把它赋给指向int的指针。然后便可使用这个指针。**例如,本例中*pt1是10,pt1[1]是20。

    还可以把复合字面量作为实际参数传递给带有匹配形式参数的函数:

    int sum(const int ar[], int n);
    ...
    int total3;
    total3 = sum((int []){4,4,4,5,5,5}, 6);
    

    这种用法的好处是,把信息传入函数前不必先创建数组,这是复合字面量的典型用法。可以把这种用法应用于二维数组或多维数组。

    int (*pt2)[4];   // 声明一个指向二维数组的指针,该数组内含2个数组
    元素,
    // 每个元素是内含4个int类型值的数组
    pt2 = (int [2][4]) { {1,2,3,-9}, {4,5,6,-8} };
    

    如上所示,该复合字面量的类型是int [2][4],即一个2×4的int数组。

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

    展开全文
  • 复合字面量 复合字面量,是除了符号常量之外的常量,例如:5是int的字面常量,1.2是double的字面常量,'a’是char的字面常量,"hello"是字符串的字面常量。一般来说,字符常量可以方便初始化变量,而且可以用于相应...
  • 复合字面量(C99)

    千次阅读 2018-07-03 14:03:48
    语法,把类型名放到圆括号里面,后面紧跟一个花括号扩起来的初始化列表。int *a = (int []){1,2};例如:#include &lt;stdio.h&gt; struct argv { char a[64]; int b; }; ...,a.a,a.b...
  • C语言复合字面量

    2018-07-08 17:10:02
    / * C99增加的特性,复合字面量(composite literal)。一旦熟悉并使用,便会体会到简洁强大的表达对,复合字面量,就是可以随时定义,随时赋值的数组字面量。两步构建出来。形如(type [])表示需要构建的数组类型...
  • 复合字面量(compound literal)

    千次阅读 2018-02-13 16:17:14
    C Primer Plus(内容笔记) 假设给带int类型形参的函数传递一个值,要传递int类型...C99新增了复合字面量 (compound literal)。字面量是除符号常量外的常量。例如,5是int类型字 面量, 81.3是double类型的字面...
  •   复合字面量是C99标准加入的,在vs2017和g++ 7.5.0中,C++不支持此语法。 二 字面量(literal)   在计算机科学中,字面量(literal)是用于表达源代码中一个固定值的表示法(notation)(字面量是相对变量常量等定义...
  • C语言复合字面量的使用

    千次阅读 2015-06-29 18:01:59
    C99增加的特性,复合字面量(composite literal)。一旦熟悉并使用,便会体会到简洁强大的表达。 所谓字面量就是固定数值的表示。数值和字符串类型都有字面量的表达。如: // 100, 1.23f, "literral" 都是字面量 int ...
  • 4.复合字面量

    千次阅读 2020-07-02 16:51:59
    复合自变量类似于数组初始化列表,前面是用括号括起来的类型名 int arr[2] = {1, 2} 用复合自变量表示方法如下 (int [2]) {1, 2} //复合自变量 有两个int类型值的匿名数组 ...复合字面量是匿名的,所.
  • c语言复合字面量

    千次阅读 2018-05-29 21:29:02
    C99新增了复合字面量,字面是除符号常量外的常量,声明格式如下:(int [2]){10,20}即去掉声明中的数组名,留下的int [2]即使复合字面量的类型名,初始化有数组名的数组时可以省略数组的大小,复合字面量也可以,...
  • //通过给出成员的名字,可以以任意顺序初始化结构变量的成员,或者只初始化部分成员 复合字面量:通过复合字面量,我们可以在一个语句中给结构变量的多个成员变量赋值。 today=(struct date){9,25,2004};//复合字面...
  • 复合字面量-指针学习

    2021-10-09 17:40:12
    前要:我们可以利用复合字面量直接创造一个数组,然后直接运用该数组作许多其他运算,而不用像之前还需声明后再使用 比如 int ar[2]={1,2}; ... 现在可以这样 (int [2]){1,2}//在我的理解中,这个式子与上式...
  • Go 中的复合字面量

    2018-08-29 10:58:00
    在源代码中字面量可以描述像数字,字符串,布尔等类型的固定值。Go 和 JavaScript、Python 语言一样,即便是复合...Golang 的复合字面量表达也很方便、简洁,使用单一语法即可实现。在 JavaScript 中它是这...
  • 复合字面量(c99) 有时候我们只需要使用某一个特定的结构体一次,那么就可以采用这样的方式。 规则:要赋值的变量=(变量类型){初始化列表}; struct book { int data; int data_2; }; int main() { struct book...
  • (C99)复合字面量

    2019-09-05 20:44:32
    #include <stdio.h> struct argvs { char a[64]; int b; }; int pfunc(struct argvs *a) { printf("argvs.a=%s argvs.b=%d\n", a->a, a->b); } int func(struct argvs a) ... printf(...
  • 复合字面量的意义?我直接声明一个数组不也一样的吗?
  • 关于复合字面量的使用问题

    千次阅读 2017-09-09 16:15:41
    复合字面量是c99新增加的特性: 首先要知道复合字面量是匿名的,也就是说你不需要为它去取去一个名字,它是需要使用到它的时候才去创建它的,十分的简洁强大 可以对比一下开辟一个普通的数组和用复合字面量表示...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,527
精华内容 4,610
关键字:

复合字面量

友情链接: linux4.zip