zoukankan      html  css  js  c++  java
  • C99标准的柔性数组 (Flexible Array)

     【什么是柔性数组(Fliexible Array)】

    柔性数组在C99中的定义是:

    6.7.2.1 Structure and union specifiers

    As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member.

    所以可以给出一个中文定义:

    在至少两个成员的结构体中,最后一个成员其类型若是不完整类型的数组类型,则该成员称为柔性数组。

    典型例子:

    struct s { int n; char str[]; };

    注意,str后面的中括号只能为空,数组类型不局限于char。

    然而GCC编译器在C99发布之前就支持str[0]作为“柔性数组”,而且str[0]可以放在任何位置。这属于GCC对C语言的语法扩展。

    这个语法扩展因为实用并且受欢迎,所以C99将其作为一个特殊情况并得到了支持。下面将具体说明。

    【柔性数组的由来和作用】

    有一些应用场景(如设计数据包)需要一个结构体里面包含因时而异的字符串,没有“柔性数组”概念之前,使用的方法是:

    复制代码
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int main(void)
    {
        struct s { int n; char *str; };
        char string[] = "ZhangHaiba";
        struct char *ptos = malloc(sizeof (struct s) + strlen(string)+1);
        strcpy(ptos+1, string);
        //get the beginning address of str
        char *p = (char *)(ptos+1);
    
        printf("%s
    ", p);
        return 0;
    }
    复制代码

    GCC超越当时的标准对C语法进行扩展,支持“柔性数组”,就可以使用下面的方法(移植性不好):

    复制代码
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int main(void)
    {
        struct s { int n; char str[0]; };
        char string[] = "ZhangHaiba";
        struct s *ptos = malloc(sizeof (struct s) + strlen(string)+1);
        strcpy(ptos->str, string);
        //get the beginning address of str
        char *p = ptos->str;
    
        printf("%s
    ", p);
        return 0;
    }
    复制代码

    下面是GCC关于“柔性数组”的官方介绍和对比:http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html

    由于上述方法符合C语言的精神(代码简单精炼),因此在C99中得到了支持。所以符合C99标准而且优雅的方法应该是:

    复制代码
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int main(void)
    {
        struct s { int n; char str[]; };
        char string[] = "ZhangHaiba";
        struct s *ptos = malloc(sizeof (struct s) + sizeof (string));
        strcpy(ptos->str, string);
        //get the beginning address of str
        char *p = ptos->str;
    
        printf("%s
    ", p);
        return 0;
    }
    复制代码

    【C99柔性数组的特点】

    柔性数组作为不完整类型,即使用struct s test定义了变量test之后,sizeof (test.str)肯定是不行的。哪怕给str分配了空间也不行。

    因为标准规定sizeof的操作数不可以是不完整类型(还有函数类型及位字段)。

    所以sizeof (struct s)或sizeof (test),不算上柔性数组str占的空间,也是情理之中了。(如果在GCC中,单独测试array[0],则显示其占空间为0字节)

    简而言之,柔性数组只是把符号(名字)放在结构体内(压根儿就没定义),方便使用.或->语法来操作柔性数组,其所占内存空间(定义时分配)并不算在结构体变量中。

    复制代码
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int main(void)
    {
        struct s { int n; char str[]; };
        char string[] = "ZhangHaiba";
        struct s *ptos = malloc(sizeof (struct s) + sizeof (string));
        strcpy(ptos->str, string);
        //get the beginning address of str
        char *p = ptos->str;
    
        printf("%s
    ", p);
    
        struct s test; //test is static allocation,str didn't alloc memory
        printf("%ld %ld
    ", sizeof test, sizeof *ptos); // *ptos is dynamic allocation, str has been alloc memory
        //printf("%ld
    ", sizeof (test.str)); //error: invalid application of ‘sizeof’ to incomplete type ‘char[]’ 
        //printf("%ld
    ", sizeof (ptos->str)); //error: invalid application of ‘sizeof’ to incomplete type ‘char[]’
        return 0;
    }
    复制代码

    @Author: 张海拔

    @Update: 2014-2-2

    @Link: http://www.cnblogs.com/zhanghaiba/p/3537561.html

  • 相关阅读:
    Web网页数据抽取软件的设计与实现
    以Groovy的方式更稳定地解析HTML(转载)
    HTML 资讯汲取(上篇) 使用 JDOM 、 TagSoup 及 XPath
    html解析
    HTML 資訊汲取(下篇) TagSoup 輸出 namespace 問題的解決方案
    国外免费主机空间
    ASP.NET获取客户端IP地址、系统版本、浏览器版本
    阁下莫非就是当年华山论剑武功独步天下罕有其匹号称一朵梨花压海棠的少林寺智障大师收养的小沙弥低能的爱犬旺财踩扁的蟑螂小强曾滚过的一个粪球?
    html中table里的col标签
    Visual Studio 2010 中的 TODO
  • 原文地址:https://www.cnblogs.com/hjbf/p/10373328.html
Copyright © 2011-2022 走看看