自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

哦!數(shù)組還能這么用,學到了!

開發(fā) 后端
即結(jié)構(gòu)體的最后一個成員,可以不完整類型(一種缺乏足夠的信息去描述一個完整對象的類型)的數(shù)組,但它使得整個結(jié)構(gòu)體的大小就像沒有這個成員一樣。

這個問題源于讀者在閱讀redis源碼時的一個疑問。

先看下面的代碼,對于包含動態(tài)字符串成員的兩個結(jié)構(gòu)體Test0和Test1占用空間分別是多少呢? 

  1. //來源:公眾號【編程珠璣】  
  2. //作者:守望先生  
  3. #include<stdio.h>  
  4. struct Test0  
  5.  
  6.     int a;  
  7.     int b;  
  8.     char *c;  
  9. };  
  10. struct Test1  
  11.  
  12.     int a;  
  13.     int b;  
  14.     char c[];  
  15. };  
  16. int main(void)  
  17.  
  18.     printf("sizeof(struct Test0) = %zd\n",sizeof(struct Test0));  
  19.     printf("sizeof(struct Test1) = %zd\n",sizeof(struct Test1));  
  20.     return 0;  

很多讀者一眼就能看出來,在64位系統(tǒng)上,編譯為64位程序,其輸出結(jié)果為: 

  1. 16  

對于Test0的結(jié)果是16,通常沒有什么疑問,畢竟4(int)+4(int)+8(指針)= 16,但是對于后者的結(jié)構(gòu)體占用空間為8字節(jié),有的讀者可能會有疑問。(關于字節(jié)對齊,參考《字節(jié)對齊,看這篇就懂了》)

柔性數(shù)組(flexible array)

實際上這是在C99中引入的柔性數(shù)組的特性。即結(jié)構(gòu)體的最后一個成員,可以不完整類型(一種缺乏足夠的信息去描述一個完整對象的類型)的數(shù)組,但它使得整個結(jié)構(gòu)體的大小就像沒有這個成員一樣。但是呢,當用結(jié)構(gòu)體通過這個名字訪問這個成員時,就像訪問一個普通數(shù)組成員一樣。

如果數(shù)組最終一個元素都沒有的話,那么訪問這個數(shù)組將會是未定義行為了。

正如我們前面所看到的: 

  1. struct Test1  
  2.  
  3.     int a;  
  4.     int b;  
  5.     char c[];  
  6. }; 

成員c是一個數(shù)組,但是并沒有指定大小,使用sizeof計算Test1,其占用空間也僅僅是8字節(jié)。

有什么好處?

那么使用柔性數(shù)組有什么好處呢?

內(nèi)存申請和釋放

假設分別使用兩種類型的結(jié)構(gòu)體,存儲16字節(jié)的字符數(shù)據(jù),需要申請內(nèi)存。對于struct Test0: 

  1. strcut Test0 *t0 = malloc(sizeof(struct Test0));//為結(jié)構(gòu)體申請內(nèi)存  
  2. t0->c = malloc(sizeof(char) * 16);//為成員指向的數(shù)據(jù)申請內(nèi)存 

而對于struct Test1: 

  1. strcut Test1 *t1 = malloc(sizeof(struct Test1) + sizeof(char) * 16); 

看出區(qū)別了嗎?前者需要兩次內(nèi)存申請,而后者只需要一次。前者地址不連續(xù)(兩次malloc),后者地址連續(xù)。而你訪問成員c的時候,只需要下面這樣就可以:

t1->c,和普通成員無異。

要判斷它們的地址是否連續(xù)也非常簡單,只需要分別打印b和c的地址就可以了。

和內(nèi)存釋放類似,前面需要單獨釋放成員c申請的內(nèi)存,而后者可以一起釋放。

數(shù)據(jù)拷貝

正由于前面的差別,導致數(shù)據(jù)拷貝時,更有區(qū)別。

對于struct Test0: 

  1. //memcpy(t0copy,t0,sizeof(struct Test0));//不可,這樣直接t0copy的c和t0的c指向同一片內(nèi)存區(qū)域。  
  2. t0t0copy.a = t0.a;  
  3. t0t0copy.b = t0.b;  
  4. memcpy(t0copy.c,t0.c,sizeof(char)*16); 

這里無法一次拷貝,因為它的成員c是一個指針類型,我們需要的是一份完整拷貝,因此必須拷貝它指向的內(nèi)存。(參考《結(jié)構(gòu)體成員賦值到底是深拷貝還是淺拷貝?》)

但是對于struct Test1: 

  1. memcpy(t0copy,t0,sizeof(strcut Test1) + sizeof(char) * 16); 

在這里,由于柔性數(shù)組的內(nèi)存,它的數(shù)據(jù)內(nèi)容和結(jié)構(gòu)體數(shù)據(jù)成員的地址是連續(xù)的,因此可以直接拷貝。

減少內(nèi)存碎片

由于結(jié)構(gòu)體的柔性數(shù)組和結(jié)構(gòu)體成員的地址是連續(xù)的,即可一同申請內(nèi)存,因此更大程度地避免了內(nèi)存碎片。另外由于該成員本身不占結(jié)構(gòu)體空間,因此,整體而言,比普通的數(shù)組成員占用空間要會稍微小點。

零長數(shù)組

與柔性數(shù)組功能類似,還有一個0長數(shù)組,不過它并不是標準中的,但是它可以實現(xiàn)類似的功能,使用方式如下: 

  1. struct Test1  
  2.  
  3.     int a;  
  4.     int b;  
  5.     char c[0];  
  6. }; 

差別在于使得數(shù)組長度為0。但是由于它并非C標準中的,因此從可移植性考慮,不建議使用這種方式,除非你還無法使用C99。

總結(jié)

柔性數(shù)組的使用:

  •  位于結(jié)構(gòu)體最后一個位置
  •  不完整數(shù)組類型
  •  不是唯一成員

最后,放張圖,看差別:

普通和柔性數(shù)組

 

 

責任編輯:龐桂玉 來源: C語言與C++編程
相關推薦

2017-03-17 13:40:48

思科視頻

2022-10-28 19:19:11

ChromeNetwork網(wǎng)絡

2021-08-29 18:13:03

緩存失效數(shù)據(jù)

2021-11-22 11:05:20

Vue 3setup前端

2020-07-21 18:54:21

Rust類型轉(zhuǎn)換語言

2019-03-28 11:07:56

Spring BootRedis緩存

2023-10-16 08:55:43

Redisson分布式

2013-03-26 13:26:41

婚禮微信微信公眾賬號

2022-02-14 21:58:58

netstatLinuxWindows

2021-03-09 09:55:02

Vuejs前端代碼

2023-04-10 07:40:36

GraphQLRest通信模式

2022-10-31 08:47:21

人臉識別按鍵鍵盤

2024-11-13 09:22:40

2023-06-03 00:05:18

TypeScriptJSDoc掃描器

2022-07-19 08:04:04

HTTP應用層協(xié)議

2020-05-09 16:45:56

ping命令Linux

2010-01-20 10:37:48

Chrome瀏覽器

2019-12-30 09:51:35

Word設計模式軟件

2024-04-12 08:54:13

從庫數(shù)據(jù)庫應用

2021-09-03 06:46:34

MyBatis緩存后端
點贊
收藏

51CTO技術棧公眾號