C99标准的柔性数组 (Flexible Array)

 

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

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

6.7.2.1 Structure and union specifiersapp

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.函数

因此能够给出一个中文定义:测试

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

典型例子:this

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

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

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

这个语法扩展由于实用而且受欢迎,因此C99将其做为一个特殊状况并获得了支持。下面将具体说明。code

 

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

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

#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\n", 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\n", 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\n", 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\n", p);

    struct s test; //test is static allocation,str didn't alloc memory
    printf("%ld %ld\n", sizeof test, sizeof *ptos); // *ptos is dynamic allocation, str has been alloc memory
    //printf("%ld\n", sizeof (test.str)); //error: invalid application of ‘sizeof’ to incomplete type ‘char[]’ 
    //printf("%ld\n", 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

相关文章
相关标签/搜索