歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

C語言中變長數組引發的思考

看到老師寫的一個結構體很好奇,結構體的最後是一個長度為0的數組,當時感覺老師是不是寫錯了,這樣寫意義何在呢?都沒有分配空間,貌似沒有存在的意義。

後來網上查了一下,其實這是在很多高級的東東裡面都用到的東西,linux kernel, MFC, openoffice, 估計更多的地方都用到了。

先說說我的理解:

struct example{
    __u16 tag_type;
    __u16 tag_len;
    char tag_data[0];
} __attribute ((packed));


1. 存在的意義:當結構體的長度變長時,例如裡面有一個字符串時,為了方便管理內存。

這個結構體不要用struct example a的方式定義, 而應用struct example *a; a = (struct example *)malloc(sizeof(struct example) + extrasize);的形式。extrasize是想額外申請的空間,就是字符串的長度。

2. 如何使用裡面的數據?

前面的數據項不用說了,後面的tag_data直接就是我們申請的額外的地址的開始地址。所以,很好用

3. 如何釋放申請的地址空間?

直接free(a)就好。有些人可能認為後面的空間沒有釋放,其實不然。因為malloc申請的空間系統是需要進行管理的,你申請了多少,當你釋放的時候,就釋放多少。並不是根據你的數據類型來的,否則你說 char *p; p  = malloc(20); 然後free(p);系統該釋放多少空間呢。 至於系統如何管理的,貌似是通過一個鏈表進行的,記不清了。

4. 附1

為了解決這個疑惑,後來看了幾篇文章,感謝他們。

後來就是人提到過有些編譯器不支持0長數組,那怎麼辦呢?很簡單,將數組長度定為1即可,這樣僅僅浪費一個字節的空間(字節對齊的話另當別論)。這樣做還有另外一個好處就是不用記錄這個字符串的長度, 因為本來就存了一個字節的空間,可用這一個字節的空間來標識這個字符串是否為空。

5.附2

有人可能會問,為什麼最後一個數據項不設置成一個指針呢?char tag_data[0]; 和char *tag_data;有什麼區別呢?

第一個問題:最好不要設置成指針,因為這樣的話,你得為tag_data指針重新申請空間,申請的空間還不連續;其次,釋放的時候很麻煩,必須先釋放內部的指針,但是這個往往是人最容易忽略而造成內存呢洩露的原因。

第二個問題:這個問題貌似問的很傻,因為這是兩種不同類型的數據,占據的地址大小都不同。其實不然,這個問題設計到指針和數組的區別問題。

 指針和數組很多人都把他們之間畫成等號了,這是個錯誤,希望各位不要犯。他們倆只有在作為函數參數的時候才是真正的一摸一樣,都是指針變量,其他情況都不一樣。最大的區別:數組是直接尋址的,指針是間接尋址的。array[0]中, array 是一個常量,等於&(a[0]); 而指針變量是一個變量。像array = a就不允許賦值(常量怎麼可能作為賦值運算符的左操作數呢?),a = array就是允許的。

6.最後

這個東西用在內存池的管理中用得很多。內存池,這個東西,說起來很嚇唬人,其實就是那麼回事。一個程序或者動態庫維護的一個全局的數組而已,無它。比如說一個c/s架構的服務器,客戶端調用一個預先編好的動態庫中的函數,一般來說不會沒發一個請求網絡就幫你投遞過去,那樣數據太小了。一般都是在動態庫中維護一個數組,把請求往裡面填,填到滿的時候發送出去;或者用戶強行要求發送出去。

這個就跟標准i/o庫很像了,其實裡面也是一段緩存,通過這個緩存使得內存和外存的數據交換不是那麼頻繁,提高了效率。用戶也可以使用fflush()函數強行寫到外存。原理都是類似的。

Copyright © Linux教程網 All Rights Reserved