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

相關文章
相關標籤/搜索