a亚洲精品_精品国产91乱码一区二区三区_亚洲精品在线免费观看视频_欧美日韩亚洲国产综合_久久久久久久久久久成人_在线区

首頁 > 編程 > C > 正文

C語言柔性數組實例詳解

2020-01-26 15:20:30
字體:
來源:轉載
供稿:網友

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

一般來說,結構中最后一個元素允許是未知大小的數組,這個數組就是柔性數組。結構中的柔性數組前面必須至少一個其他成員,柔性數組成員允許結構中包含一個大小可變的數組,sizeof返回的這種結構大小不包括柔性數組的內存。包含柔數組成員的結構用malloc函數進行內存的動態分配,且分配的內存應該大于結構的大小以適應柔性數組的預期大小。柔性數組到底如何使用?

不完整類型

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

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

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

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

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

extern int a[];

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

int a[] = { 10,20 };

結構體

首先,我們需要知道――所謂變量,其實是內存地址的一個抽像名字罷了。在靜態編譯的程序中,所有的變量名都會在編譯時被轉成內存地址。機器是不知道我們取的名字的,只知道地址。

所以有了――棧內存區,堆內存區,靜態內存區,常量內存區,我們代碼中的所有變量都會被編譯器預先放到這些內存區中。

有了上面這個基礎,我們來看一下結構體中的成員的地址是什么?我們先簡單化一下代碼:

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

上面代碼中,test結構中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;}

運行結果:

我們可以看到,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了的地址。于是,你就知道,不管結構體的實例是什么――訪問其成員其實就是加成員的偏移量。

下面再來做個實驗:

#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;}

運行結果:

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

柔性數組

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

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

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

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成了多余的東西,可以去掉。但是,又產生了另外一個問題:老是使用(char*)(ptestt + 1)不方便。如果能夠找出一種方法,既能直接引用該字符串,又不占用結構體的空間,就完美了,符合這種條件的代碼結構應該是一個非對象的符號地址,在結構體的尾部放置一個0長度的數組是一個絕妙的解決方案。不過,C/C++標準規定不能定義長度為0的數組,因此,有些編譯器就把0長度的數組成員作為自己的非標準擴展,例如:

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

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

鑒于這種代碼結構所產生的重要作用,C99甚至把它收入了標準中:

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使用不完整類型實現柔性數組成員,標準形式是這樣的:

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

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

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

首先,我們要知道,0長度的數組在ISO C和C++的規格說明書中是不允許的。這也就是為什么在VC++2012下編譯你會得到一個警告:“arning C4200: 使用了非標準擴展 : 結構/聯合中的零大小數組”。

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

#include <stdlib.h>#include <string.h>struct line {  int length;  char contents[0]; // C99的玩法是:char contents[]; 沒有指定數組長度};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;}

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

相信本文所述對大家C程序設計的學習有一定的借鑒價值。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

主站蜘蛛池模板: 欧美一区2区三区3区公司 | 日韩中文字幕电影在线观看 | 狠狠久久| 亚州中文字幕 | 国产精品对白一区二区三区 | 日韩在线精品视频 | 久国久产久精永久网页 | 中文字幕在线资源 | www.com91| 国产精品99久久久久久宅男 | 国产成人在线免费观看 | 欧美日韩在线免费观看 | 国产欧美精品一区二区 | 国产一区二区三区四区在线观看 | 精品久久久久久国产 | 影音先锋国产 | 精品久久中文字幕 | 免费在线小视频 | 一区二区精品视频 | 四虎影院最新网站 | 91中文字幕在线 | 欧美精品一区二区三区在线 | 日韩av免费在线观看 | 成人国产精品久久 | 国产精品伦一区二区三级视频 | 久久久一区二区 | 欧美日日干 | 欧美乱妇高清无乱码 | 99动漫 | 免费观看成人性生生活片 | 欧美三级视频在线观看 | 制服 丝袜 综合 日韩 欧美 | 国产亚洲综合一区二区 | 久久视频一区二区 | 欧美精品一区二区三区四区五区 | 蜜桃av导航 | 色接久久 | 国产精品久久久久久久久久久久久久 | 欧美精品一区二区三区一线天视频 | 精品视频免费观看 | 蜜桃精品久久久久久久免费影院 |