<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>
"); //-->

博客專(zhuān)欄

EEPW首頁(yè) > 博客 > C語(yǔ)言柔性數組詳解

C語(yǔ)言柔性數組詳解

發(fā)布人:電子禪石 時(shí)間:2023-02-19 來(lái)源:工程師 發(fā)布文章
一、柔性數組是什么?

C99中,結構體中的最后一個(gè)元素允許是未知大小的數組,這就叫作柔性數組,for example:

 struct st_type{
	int i;
	int a[0];//柔性數組成員,也可以寫(xiě)int a[];};

結構體成員a數組,它的數組大小是沒(méi)有確定的,將來(lái)如果需要可以大也可以小。
有些編譯器支持a[0]這種寫(xiě)法,有些編譯器支持a[ ]這種寫(xiě)法,具體取決編譯器。


二、柔性數組的特點(diǎn)

1.結構體中柔性數組成員前面必須至少有一個(gè)其他成員

示例如下:


 struct st_type

{

int i;

int a[0];//柔性數組成員,也可以寫(xiě)int a[];

};


比如上面這段代碼,如果你要創(chuàng )建一個(gè)柔性數組a,前面必須創(chuàng )建一些別的成員

————————————————

2.sizeof返回的這種結構大小不包括柔性數組的內存

 struct st_type
{
	int i;//4字節
	int a[0];//柔性數組成員,也可以寫(xiě)int a[];
	//因為是柔性數組,無(wú)法確認a占幾個(gè)字節
};
 int main()
 {
	 printf("%d\n", sizeof(struct st_type));//打印4
	 return 0;
 }

這里計算包含柔性數組的結構體大小,因為柔性數組本身是無(wú)法確定有幾個(gè)字節的,所以計算整體結構體大小時(shí),會(huì )省略柔性數組的計算。


3.包含柔性數組成員的結構用malloc()函數進(jìn)行內存的動(dòng)態(tài)分配,并且分配的內存應該大于結構的大小,以適應柔性數組的預期大小

ps:除了malloc函數,realloc、calloc等動(dòng)態(tài)內存開(kāi)辟的函數也需要類(lèi)似的操作


比如說(shuō)我現在要數組a里面有10個(gè)元素,現在進(jìn)行malloc一下

————————————————

示例如下:

#include<string.h>
#include<errno.h>
struct st_type
{
	int i;//4字節
	int a[0];//柔性數組成員,也可以寫(xiě)int a[];
};
int main()
{
    //假設我現在需要a里有10個(gè)元素
	struct st_type*ps=(struct st_type*)malloc(sizeof(struct st_type) + 10 * sizeof(int));
	if (ps == NULL)//由于空間可能不夠開(kāi)辟導致malloc開(kāi)辟失敗,開(kāi)辟失敗會(huì )返回空指針
	{
		printf("%s\n", strerror(errno));
		return -1;//程序出問(wèn)題后,跳出程序
	}
	//開(kāi)辟成功
	int j = 0;
	for (j = 0;j < 10;j++)
	{
		ps->a[j] = j;
	}
	for (j = 0;j < 10;j++)
	{
		printf("%d ", ps->a[j]);//打印0-9
	}
	printf("\n");
	//如果想繼續用柔性數組a進(jìn)行打印
	//比如現在a里只有10個(gè)元素,我用完10個(gè)了,我還要繼續來(lái)10個(gè),用realloc追加
	struct st_type*ptr=realloc(ps, sizeof(struct st_type) + 20 * sizeof(int));//ps:realloc第二個(gè)參數是調整后的整體大小
	if (ptr == NULL)
	{
		printf("擴容失敗\n");
		return -1;
	}
	else
	{
		ps = ptr;
	}
	//擴容成功
	int k = 0;
	for (k = 10;k < 20;k++)
	{
		ps->a[k] = k;
	}
	for (j = 0;j < 20;j++)
	{
		printf("%d ", ps->a[j]);//打印0-19
	}
	//釋放空間
	free(ps);
	ps = NULL;
	return 0;
}

image.png


我們這里需要數組a里有10個(gè)元素,那我們malloc的時(shí)候要對結構體里的整形i先開(kāi)辟4個(gè)字節,然后為整形數組a再開(kāi)辟40個(gè)字節,然后malloc函數返回開(kāi)辟空間的起始地址,賦給truct st_type * 類(lèi)型的ps指針。


malloc(sizeof(struct st_type) + 10 * sizeof(int))這個(gè)操作等價(jià)于struct st_type類(lèi)型創(chuàng )建一個(gè)變量所占空間,只不過(guò)是用malloc來(lái)開(kāi)辟


你改變數組a大小,追加空間時(shí),realloc(ps, sizeof(struct st_type) + 20 * sizeof(int)),realloc的第一個(gè)參數仍然是ps,因為你當時(shí)是用malloc一次開(kāi)辟出的一塊空間,你是不能單獨調整數組a的空間的

————————————————

三、柔性數組的優(yōu)點(diǎn)

柔性數組就是對一塊空間實(shí)現動(dòng)態(tài)開(kāi)辟嘛,那我們之前也講過(guò)指針來(lái)動(dòng)態(tài)內存開(kāi)辟,我們來(lái)看一段代碼來(lái)對比一下這兩種方法:

//用指針也可以做到a指向的空間動(dòng)態(tài)變化
struct st_type
{
	int i;//4字節
	int *a;//4字節,這里計算結構體大小恰好是8字節
};
int main()
{
	struct st_type*ps = (struct st_type*)malloc(sizeof(struct st_type));
	ps->i = 100;
	ps->a = (int*)malloc(10 * sizeof(int));//a指向40個(gè)字節的空間,該空間由int*進(jìn)行管理
	int j = 0;
	for (j = 0;j < 10;j++)
	{
		ps->a[j] = j;//a[j]=*(a+j)
	}
	for (j = 0;j < 10;j++)
	{
		printf("%d", ps->a[j]);
	}
	//a指向的空間不夠了,希望調整大小
	int *ptr = (int*)realloc(ps->a, 20 * sizeof(int));
	if (ptr == NULL)
	{
		printf("擴容失敗");
		return -1;
	}
	else
	{
		ps->a = ptr;
	}
	//使用...
	//釋放
	free(ps->a);
	ps->a = NULL;
	free(ps);
	ps = NULL;
}

這里需要注意的是,在釋放空間時(shí),你要先釋放指針a指向的空間,然后釋放結構體指針。


image.png

如上圖,我們結構體指針ps開(kāi)辟一塊空間,空間里存放整形i和整形指針a,a又malloc(后續如果需要還可以realloc追加)一塊空間,如果你先釋放掉ps,a就沒(méi)了,你就沒(méi)法找到a指向的那塊空間了。

還是那個(gè)生動(dòng)的例子 就比如a是一個(gè)警察頭子,malloc開(kāi)辟的空間是臥底,只有a知道那個(gè)臥底,你現在警察頭子死了,再也沒(méi)法證明臥底是臥底了,也就是說(shuō)a消失后,沒(méi)辦法再對開(kāi)辟的空間進(jìn)行釋放,這時(shí)就會(huì )造成內存泄露,指針實(shí)現動(dòng)態(tài)內存調整是需要對指針釋放講解一定的順序性的

————————————————

這里對比柔性數組,柔性數組和上述的指針都可以實(shí)現一塊空間大小的調整,但是柔性數組有兩個(gè)好處:

第一個(gè)好處是:方便內存釋放

如果我們的代碼是在一個(gè)給別人用的函數中,你在里面做了二次內存分配,并把整個(gè)結構體返回給用戶(hù)。用戶(hù)調用free可以釋放結構體,但是用戶(hù)并不知道這個(gè)結構體內的成員也需要free,所以你不能指望用戶(hù)來(lái)發(fā)現這個(gè)事。以上,如果我把結構體的內存及其成員要的內存一次性分配好,并返回給用戶(hù)一個(gè)結構體指針,用戶(hù)做一次free就可以把所有內存都釋放掉,并且不用考慮前面說(shuō)的釋放的順序。

————————————————

第二個(gè)好處是:加快訪(fǎng)問(wèn)速度
連續的內存有益于提高訪(fǎng)問(wèn)速度,也有益于減少內存碎片。
ps:內存碎片如下圖

image.png


總結

本文介紹了柔性數組的定義、其三個(gè)使用特點(diǎn),及其對比指針實(shí)現動(dòng)態(tài)內存的優(yōu)勢,并對其進(jìn)行了具體舉例,知識點(diǎn)并不復雜,希望讀者學(xué)習完本文后能對柔性數組有更進(jìn)一步的理解,祝讀者生活愉快!


*博客內容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀(guān)點(diǎn),如有侵權請聯(lián)系工作人員刪除。



關(guān)鍵詞: c

相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>