在標準 c 和 c++ 中,不允許用 0 長度陣列,但在 gnu c 中,卻可以定義 0 長度陣列。比如:
引用struct
line
0 長度陣列不占有空間,從列印 sizeof (struct line) 可以看到這個結構體的長度為 4,這 4 位元組空間屬於整型量 length 。那麼結構體裡最後的 0 長度字元陣列 contents[0] 用來做什麼呢?答案是,它可以用來指向一段由你自己分配的 buffer 空間。如:
引用int
this_length
=60;
struct
line
*thisline
= (struct
line
*) malloc (
sizeof(
struct
line)
+this_length);
thisline->length = this_length;
這樣,就開闢了 64 位元組空間。前面 4 個位元組為 this_length 用,後面 60 個位元組被 contents 陣列用。經過空間分配後,就相當於把結構體定義為:
引用struct
line
順便看一下這個空間的分布,做如下列印:
引用printf (
"thisline 指向的位址為 %p
/n
",thisline);
printf (
"thisline指向的第乙個元素值為:%d
/n
",thisline
->
length);
printf (
"該元素的位址為%p
/n
",&thisline
->
length);
printf (
"%p/n
",&thisline
->
contents);
printf (
"%p/n
",&thisline
->
contents[0
]);printf (
"%p/n
",&thisline
->
contents[1
]);
輸出為:
引用thisline 指向的位址為 0x8780008
thisline指向的第乙個元素值為:60
該元素的位址為0x8780008
0x878000c
0x878000c
0x878000d
從輸出可以看到,thisline-contents 只是乙個「不占有空間「(其特性由編譯器決定)的常量指標。在這裡,它表示接著整型值後的起始位址。
現在,我們可以使用這個陣列了,比如給這個陣列的前幾個元素賦下值:
引用char
c='x';
int
i;thisline
->
contents[0
]=c; c=
'y';
thisline
->
contents[1
]=c; c=
'z';
thisline
->
contents[2
]=c;
for(
i=0; i
<
3; i
++)
printf (
"%c/n
",thisline
->
contents[i
]);
還有乙個問題需要**。既然用了 malloc() 函式,那麼在最後就會使用 free() 函式來釋放掉所申請的記憶體空間。那麼,在這裡,是不是只是用 free(thisline) 就能達到目的了呢?下面做乙個實驗:
首先在程式中,將分配緩衝區的首位址備份起來:
引用struct
line
*thisline_bak
=thisline;
現在做如下釋放然後看一下空間中首元素(length)的值:
引用free(thisline);
printf (
"%d/n
",thisline_bak
->
length);
一般在列印裡可以看到 length 的輸出值為 0 ,這也說明,首個元素的記憶體空間確實被釋放了。在這裡,嚴格的說,這個指標已經不能再這麼用,因為它指向了乙個被釋放的記憶體空間。
但是,如果我們再次執行
引用for(
i=0; i
<
3; i
++)
printf (
"%c/n
",thisline
->
contents[i
]);
這個列印,發現仍然能夠正常的列印出值來,從而說明了,後面申請的陣列緩衝區還沒釋放。原因是,由於分配的空間返回的指標被強制轉換為 struct line 型別,且所得到的空間並不是平緩的(包含的不是同一種元素型別的空間)。在這裡的空間組成是,乙個整型值 + 後面一大塊字元型緩衝區。所以,在釋放時,free() 函式認為 *thisline 只是乙個指向 4 位元組整型值的空間。因而,我們要完全釋放整個申請的空間,還需要:
引用free (thisline->contents);
此後,如果再次列印之前那 3 個賦值的元素時,會發現段錯誤,或者是類似下面的錯誤:
引用*** glibc detected *** ./array4: free(): invalid pointer: 0x09e4300c ***
*****== backtrace: *****====
/lib/tls/i686/cmov/libc.so.6(+0x6b591)[0x5b8591]
/lib/tls/i686/cmov/libc.so.6(+0x6cde8)[0x5b9de8]
/lib/tls/i686/cmov/libc.so.6(cfree+0x6d)[0x5bcecd]
./array4[0x80485ad]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0x563bd6]
./array4[0x80483c1]
*****== memory map: *****===
... ...
所以,在不用這段空間時,可如下釋放:
引用free (thisline->contents); /*先釋放掉後面的陣列buffer*/
free(thisline); /*再釋放掉 4 位元組整型空間*/
0長度陣列問題
標準c c 不支援0長度陣列,gnu支援 struct node int main int argc,char argv 上述 輸出為12,0長度陣列不占用記憶體空間 中e表示乙個常量指標,這個特性由編譯器來實現的,故具有不可移植性 對於這個用法,我們定義的結構體指標可以指向任意長度的記憶體buff...
柔性陣列(0長度陣列)
柔性陣列這個概念相信大多數人博友都沒有聽說過,但是它確實存在。在c99中,結構 結構體 的最後乙個元素允許是未知大小的陣列,這就叫做柔性陣列成員。比如 struct s 或者是 struct s 一 結構中柔性陣列成員前面必須至少有乙個其他成員比如,當你建立含有柔性陣列成員的結構體時,結構體成員不能...
結構體0長度陣列的作用
在標準 c 和 c 中,不允許用 0 長度陣列,但在 gnu c 中,卻可以定義 0 長度陣列。比如 引用 struct line 0 長度陣列不占有空間,從列印 sizeof struct line 可以看到這個結構體的長度為 4,這 4 位元組空間屬於整型量 length 那麼結構體裡最後的 0...