最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語言柔性數(shù)組實例詳解

 更新時間:2014年09月10日 10:47:57   投稿:shichen2014  
這篇文章主要介紹了C語言柔性數(shù)組,通過實例分析了不完整類型、結(jié)構(gòu)體及柔性數(shù)組等概念,需要的朋友可以參考下

本文實例分析了C語言柔性數(shù)組的概念及用法,對于進(jìn)一步學(xué)習(xí)C程序設(shè)計有一定的借鑒價值。分享給大家供大家參考。具體如下:

一般來說,結(jié)構(gòu)中最后一個元素允許是未知大小的數(shù)組,這個數(shù)組就是柔性數(shù)組。結(jié)構(gòu)中的柔性數(shù)組前面必須至少一個其他成員,柔性數(shù)組成員允許結(jié)構(gòu)中包含一個大小可變的數(shù)組,sizeof返回的這種結(jié)構(gòu)大小不包括柔性數(shù)組的內(nèi)存。包含柔數(shù)組成員的結(jié)構(gòu)用malloc函數(shù)進(jìn)行內(nèi)存的動態(tài)分配,且分配的內(nèi)存應(yīng)該大于結(jié)構(gòu)的大小以適應(yīng)柔性數(shù)組的預(yù)期大小。柔性數(shù)組到底如何使用?

不完整類型

C和C++對于不完整類型的定義是一樣的,不完整類型是這樣一種類型,它缺乏足夠的信息例如長度去描述一個完整的對象。

不完整類型舉例:
前向聲明就是一種常用的不完整類型

struct test; //test 只給出了聲明,沒有給出定義

不完整數(shù)據(jù)類型必須通過某種方式補充完整,才能使它們進(jìn)行實例化。否則只能用于定義指針或引用,因為此時實例化的是指針或引用本身,不是base和test對象

一個未知長度的數(shù)組也屬于不完整類型:

extern int a[];

extern 關(guān)鍵字不能去掉,因為數(shù)組的長度未知,不能作為定義出現(xiàn)。不完整類型的數(shù)組需要補充完整才能使用。不完整類型的數(shù)組可以通過幾種方式補充完整,大括號形式的初始化就是其中的一種方式:

int a[] = { 10,20 };

結(jié)構(gòu)體

首先,我們需要知道——所謂變量,其實是內(nèi)存地址的一個抽像名字罷了。在靜態(tài)編譯的程序中,所有的變量名都會在編譯時被轉(zhuǎn)成內(nèi)存地址。機器是不知道我們?nèi)〉拿值模恢赖刂贰?/p>

所以有了——棧內(nèi)存區(qū),堆內(nèi)存區(qū),靜態(tài)內(nèi)存區(qū),常量內(nèi)存區(qū),我們代碼中的所有變量都會被編譯器預(yù)先放到這些內(nèi)存區(qū)中。

有了上面這個基礎(chǔ),我們來看一下結(jié)構(gòu)體中的成員的地址是什么?我們先簡單化一下代碼:

struct test{
  int i;
  char *p;
};

上面代碼中,test結(jié)構(gòu)中i和p指針,在C的編譯器中保存的是相對地址——也就是說,他們的地址是相對于struct test的實例的。如果我們有這樣的代碼:

struct test t;

下面做個實驗:

#include<stdio.h>
struct test{
  int i;
  char *p;
};
int main(void)
{
  struct test t;
  printf("%p\n", &t);
  printf("%p\n", &(t.i));
  printf("%p\n", &(t.p));
  return 0;
}

運行結(jié)果:

我們可以看到,t.i的地址和t的地址是一樣的,t.p的址址相對于t的地址多了個8。說白了,t.i 其實就是(&t + 0×0), t.p 的其實就是 (&t + 0×8)。0×0和0×8這個偏移地址就是成員i和p在編譯時就被編譯器給hard code了的地址。于是,你就知道,不管結(jié)構(gòu)體的實例是什么——訪問其成員其實就是加成員的偏移量。

下面再來做個實驗:

#include<stdio.h>
struct test{
  int i;
  short c;
  char *p;
};
int main(void)
{
  struct test *pt=NULL;
  printf("%p\n", &(pt->i));
  printf("%p\n", &(pt->c));
  printf("%p\n", &(pt->p));
  return 0;
}

運行結(jié)果:

注意:上面的pt->p的偏移之所以是0×8而不是0×6,是因為內(nèi)存對齊了(我在64位系統(tǒng)上)。關(guān)于內(nèi)存對齊,具體可以參看本站C語言內(nèi)存對齊實例詳解一文。

柔性數(shù)組

柔性數(shù)組成員(flexible array member)也叫伸縮性數(shù)組成員,這種代碼結(jié)構(gòu)產(chǎn)生于對動態(tài)結(jié)構(gòu)體的需求。在日常的編程中,有時候需要在結(jié)構(gòu)體中存放一個長度動態(tài)的字符串,一般的做法,是在結(jié)構(gòu)體中定義一個指針成員,這個指針成員指向該字符串所在的動態(tài)內(nèi)存空間,例如:

struct s_test
{
  int a;
  double b;
  char* p;
};

p指向字符串,這種方法造成字符串與結(jié)構(gòu)體是分離的,不利于操作。把字符串和結(jié)構(gòu)體連在一起的話,效果會更好,可以修改如下:

char a[] = "Hello world";
struct s_test *ptest = (struct s_test*)malloc(sizeof(s_test)+streln(a)+1);
strcpy(ptest+1,a);

這樣一來,(char*)(ptestt + 1)就是字符串“hello world”的地址。這時候p成了多余的東西,可以去掉。但是,又產(chǎn)生了另外一個問題:老是使用(char*)(ptestt + 1)不方便。如果能夠找出一種方法,既能直接引用該字符串,又不占用結(jié)構(gòu)體的空間,就完美了,符合這種條件的代碼結(jié)構(gòu)應(yīng)該是一個非對象的符號地址,在結(jié)構(gòu)體的尾部放置一個0長度的數(shù)組是一個絕妙的解決方案。不過,C/C++標(biāo)準(zhǔn)規(guī)定不能定義長度為0的數(shù)組,因此,有些編譯器就把0長度的數(shù)組成員作為自己的非標(biāo)準(zhǔn)擴展,例如:

struct s_test2
{
  int a;
  double b;
  char c[0];
};

c就叫柔性數(shù)組成員,如果把ptest指向的動態(tài)分配內(nèi)存看作一個整體,c就是一個長度可以動態(tài)變化的結(jié)構(gòu)體成員,柔性一詞來源于此。c的長度為0,因此它不占用test的空間,同時ptest->c就是“hello world”的首地址,不需要再使用(char*)(ptestt + 1)這么丑陋的語法了。

鑒于這種代碼結(jié)構(gòu)所產(chǎn)生的重要作用,C99甚至把它收入了標(biāo)準(zhǔn)中:

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.
C99使用不完整類型實現(xiàn)柔性數(shù)組成員,標(biāo)準(zhǔn)形式是這樣的:

struct s_test
{
 int a;
 double b;
 char c[];
};

c同樣不占用test的空間,只作為一個符號地址存在,而且必須是結(jié)構(gòu)體的最后一個成員。柔性數(shù)組成員不僅可以用于字符數(shù)組,還可以是元素為其它類型的數(shù)組,例如:

struct s_test
{
  int a;
  double b;
  float[];
};

首先,我們要知道,0長度的數(shù)組在ISO C和C++的規(guī)格說明書中是不允許的。這也就是為什么在VC++2012下編譯你會得到一個警告:“arning C4200: 使用了非標(biāo)準(zhǔn)擴展 : 結(jié)構(gòu)/聯(lián)合中的零大小數(shù)組”。

那么為什么gcc可以通過而連一個警告都沒有?那是因為gcc 為了預(yù)先支持C99的這種玩法,所以,讓“零長度數(shù)組”這種玩法合法了。關(guān)于GCC對于這個事的文檔在這里:“Arrays of Length Zero”,文檔中給了一個例子,完整代碼如下:

#include <stdlib.h>
#include <string.h>
struct line {
  int length;
  char contents[0]; // C99的玩法是:char contents[]; 沒有指定數(shù)組長度
};
int main(){
  int this_length=10;
  struct line *thisline = (struct line *)
           malloc (sizeof (struct line) + this_length);
  thisline->length = this_length;
  memset(thisline->contents, 'a', this_length);
  return 0;
}

上面這段代碼的意思是:我想分配一個不定長的數(shù)組,于是我有一個結(jié)構(gòu)體,其中有兩個成員,一個是length,代表數(shù)組的長度,一個是contents,代碼數(shù)組的內(nèi)容。后面代碼里的 this_length(長度是10)代表是想分配的數(shù)據(jù)的長度。

相信本文所述對大家C程序設(shè)計的學(xué)習(xí)有一定的借鑒價值。

相關(guān)文章

  • C語言中數(shù)組作為函數(shù)的參數(shù)以及返回值的使用簡單入門

    C語言中數(shù)組作為函數(shù)的參數(shù)以及返回值的使用簡單入門

    這篇文章主要介紹了C語言中數(shù)組作為函數(shù)的參數(shù)以及返回值的使用簡單入門,這里以一維數(shù)組作為基本條件進(jìn)行例子講解,需要的朋友可以參考下
    2015-12-12
  • C++中唯一三元運算符?:實例詳解

    C++中唯一三元運算符?:實例詳解

    這篇文章主要給大家介紹了關(guān)于C++中唯一三元運算符?:的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • 基于Matlab LBP實現(xiàn)植物葉片識別功能

    基于Matlab LBP實現(xiàn)植物葉片識別功能

    局部二值模式(LBP)是由Ojala等人于2002年提出,它被用于特征提取,而且提取的特征是圖像的紋理特征。本文將利用Matlab和LBP實現(xiàn)植物葉片識別,需要的可以參考一下
    2022-02-02
  • DEVC++實現(xiàn)推箱子小游戲

    DEVC++實現(xiàn)推箱子小游戲

    這篇文章主要為大家詳細(xì)介紹了DEVC++實現(xiàn)推箱子小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-01-01
  • C指針原理教程之Ncurses介紹

    C指針原理教程之Ncurses介紹

    Ncurses 提供字符終端處理庫,包括面板和菜單。為了能夠使用ncurses庫,您必須在您的源程序中將curses.h包括(include)進(jìn)來,而且在編譯的需要與它連接起來. 在gcc中您可以使用參數(shù)-lcurses進(jìn)行編譯.
    2019-02-02
  • C語言實現(xiàn)文本編輯器系統(tǒng)

    C語言實現(xiàn)文本編輯器系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)文本編輯器系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • C語言實現(xiàn)自行車存放管理系統(tǒng)

    C語言實現(xiàn)自行車存放管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)自行車存放管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • C++日期和時間編程小結(jié)

    C++日期和時間編程小結(jié)

    這篇文章主要介紹了C++日期和時間編程小結(jié)的相關(guān)資料,需要的朋友可以參考下
    2022-12-12
  • 基于排列與組合輸出多少中情況詳解

    基于排列與組合輸出多少中情況詳解

    本篇文章對排列與組合輸出多少中情況進(jìn)行了介紹。需要的朋友參考下
    2013-05-05
  • Clion-MinGW編譯后的exe文件添加ico圖標(biāo)的操作方法

    Clion-MinGW編譯后的exe文件添加ico圖標(biāo)的操作方法

    這篇文章主要介紹了Clion-MinGW編譯后的exe文件添加ico圖標(biāo)的操作方法,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07

最新評論

孟州市| 东乡县| 贵阳市| 九台市| 兰考县| 九龙县| 平远县| 金昌市| 赞皇县| 贵德县| 陆良县| 那坡县| 永泰县| 武穴市| 莱芜市| 三河市| 竹北市| 台湾省| 雅江县| 中阳县| 大荔县| 雷山县| 江永县| 怀来县| 宜章县| 芮城县| 邛崃市| 赣州市| 大厂| 玛曲县| 巴青县| 天门市| 常熟市| 珠海市| 莎车县| 新巴尔虎左旗| 自治县| 松原市| 荔浦县| 葵青区| 景东|