最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語言柔性數(shù)組詳解

 更新時間:2021年10月10日 17:10:33   作者:高郵吳少  
這篇文章主要介紹了C語言柔性數(shù)組,通過實例分析了不完整類型、結(jié)構(gòu)體及柔性數(shù)組等概念,需要的朋友可以參考下,希望能夠給你帶來幫助

前言

可能大家第一眼看到這個標題會有點懵,到底什么是柔性數(shù)組,我怎么從來沒聽說過?但柔性數(shù)組確實是存在的,也經(jīng)常會出現(xiàn)在一些公司的面試題中,今天就跟著筆者來學習一下柔性數(shù)組吧。

提示:以下是本篇文章正文內(nèi)容,下面案例可供參考

在這里插入圖片描述

一、柔性數(shù)組是什么?

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

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

結(jié)構(gòu)體成員a數(shù)組,它的數(shù)組大小是沒有確定的,將來如果需要可以大也可以小。
有些編譯器支持a[0]這種寫法,有些編譯器支持a[ ]這種寫法,具體取決編譯器。

二、柔性數(shù)組的特點

1.結(jié)構(gòu)體中柔性數(shù)組成員前面必須至少有一個其他成員

示例如下:

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

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

2.sizeof返回的這種結(jié)構(gòu)大小不包括柔性數(shù)組的內(nèi)存

示例如下:

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

這里計算包含柔性數(shù)組的結(jié)構(gòu)體大小,因為柔性數(shù)組本身是無法確定有幾個字節(jié)的,所以計算整體結(jié)構(gòu)體大小時,會省略柔性數(shù)組的計算。

3.包含柔性數(shù)組成員的結(jié)構(gòu)用malloc()函數(shù)進行內(nèi)存的動態(tài)分配,并且分配的內(nèi)存應該大于結(jié)構(gòu)的大小,以適應柔性數(shù)組的預期大小

ps:除了malloc函數(shù),realloc、calloc等動態(tài)內(nèi)存開辟的函數(shù)也需要類似的操作

比如說我現(xiàn)在要數(shù)組a里面有10個元素,現(xiàn)在進行malloc一下

示例如下:

#include<string.h>
#include<errno.h>
struct st_type
{
	int i;//4字節(jié)
	int a[0];//柔性數(shù)組成員,也可以寫int a[];
};
int main()
{
    //假設我現(xiàn)在需要a里有10個元素
	struct st_type*ps=(struct st_type*)malloc(sizeof(struct st_type) + 10 * sizeof(int));
	if (ps == NULL)//由于空間可能不夠開辟導致malloc開辟失敗,開辟失敗會返回空指針
	{
		printf("%s\n", strerror(errno));
		return -1;//程序出問題后,跳出程序
	}
	//開辟成功
	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");
	//如果想繼續(xù)用柔性數(shù)組a進行打印
	//比如現(xiàn)在a里只有10個元素,我用完10個了,我還要繼續(xù)來10個,用realloc追加
	struct st_type*ptr=realloc(ps, sizeof(struct st_type) + 20 * sizeof(int));//ps:realloc第二個參數(shù)是調(diào)整后的整體大小
	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;
}

在這里插入圖片描述

在這里插入圖片描述

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

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

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

三、柔性數(shù)組的優(yōu)點

柔性數(shù)組就是對一塊空間實現(xiàn)動態(tài)開辟嘛,那我們之前也講過指針來動態(tài)內(nèi)存開辟,我們來看一段代碼來對比一下這兩種方法:

//用指針也可以做到a指向的空間動態(tài)變化
struct st_type
{
	int i;//4字節(jié)
	int *a;//4字節(jié),這里計算結(jié)構(gòu)體大小恰好是8字節(jié)
};
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個字節(jié)的空間,該空間由int*進行管理
	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指向的空間不夠了,希望調(diào)整大小
	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;
}

這里需要注意的是,在釋放空間時,你要先釋放指針a指向的空間,然后釋放結(jié)構(gòu)體指針

在這里插入圖片描述

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

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

這里對比柔性數(shù)組,柔性數(shù)組和上述的指針都可以實現(xiàn)一塊空間大小的調(diào)整,但是柔性數(shù)組有兩個好處:
第一個好處是:方便內(nèi)存釋放

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

第二個好處是:加快訪問速度

連續(xù)的內(nèi)存有益于提高訪問速度,也有益于減少內(nèi)存碎片。

ps:內(nèi)存碎片如下圖

在這里插入圖片描述

操作系統(tǒng)給我們一塊內(nèi)存,我們在進行malloc時,不一定就是一塊連著一塊的,上圖的空白部分就是內(nèi)存碎片,有些類似我們裁剪布料,一些剩余的邊角料這樣。

總結(jié)

本文介紹了柔性數(shù)組的定義、其三個使用特點,及其對比指針實現(xiàn)動態(tài)內(nèi)存的優(yōu)勢,并對其進行了具體舉例

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注腳本之家的更多內(nèi)容!

相關文章

  • 簡要對比C語言中的dup()函數(shù)和dup2()函數(shù)

    簡要對比C語言中的dup()函數(shù)和dup2()函數(shù)

    這篇文章主要介紹了簡要對比C語言中的dup()函數(shù)和dup2()函數(shù),是C語言入門學習中的基礎知識,需要的朋友可以參考下
    2015-08-08
  • C語言中isalnum()函數(shù)和isalpha()函數(shù)的對比使用

    C語言中isalnum()函數(shù)和isalpha()函數(shù)的對比使用

    這篇文章主要介紹了C語言中isalnum()函數(shù)和isalpha()函數(shù)的對比使用,都可以判斷是否為字母但isalnum的判斷還包括數(shù)字,需要的朋友可以參考下
    2015-08-08
  • C++ 變量的聲明和初始化方式示例詳解

    C++ 變量的聲明和初始化方式示例詳解

    在 C++ 中,直接初始化和復制初始化之間有一些微妙的區(qū)別,通常,直接初始化更加高效并且可以用于更多的情況,因為它在聲明的同時就執(zhí)行了初始化操作,這篇文章主要介紹了C++ 變量的聲明和初始化方式示例,需要的朋友可以參考下
    2024-06-06
  • C++ Boost Chrono實現(xiàn)計時碼表流程詳解

    C++ Boost Chrono實現(xiàn)計時碼表流程詳解

    Boost是為C++語言標準庫提供擴展的一些C++程序庫的總稱。Boost庫是一個可移植、提供源代碼的C++庫,作為標準庫的后備,是C++標準化進程的開發(fā)引擎之一,是為C++語言標準庫提供擴展的一些C++程序庫的總稱
    2022-11-11
  • c++ 盡量不要使用#define 而是用const、enum、inline替換。

    c++ 盡量不要使用#define 而是用const、enum、inline替換。

    為什么這么說呢?或許很多程序員已經(jīng)習慣在文件開始使用大量的#define語句
    2013-01-01
  • C++中如何修改const變量你知道嗎

    C++中如何修改const變量你知道嗎

    這篇文章主要為大家詳細介紹了C++修改const變量,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • C++ 轉(zhuǎn)換函數(shù)用法案例詳解

    C++ 轉(zhuǎn)換函數(shù)用法案例詳解

    這篇文章主要介紹了C++ 轉(zhuǎn)換函數(shù)用法案例詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • C++命名空間5種常見用法實例解析

    C++命名空間5種常見用法實例解析

    這篇文章主要介紹了C++命名空間5種常見用法實例解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-06-06
  • C++實現(xiàn)折半查找

    C++實現(xiàn)折半查找

    這篇文章主要為大家詳細介紹了C++實現(xiàn)折半查找,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • C++ Boost Coroutine使用協(xié)程詳解

    C++ Boost Coroutine使用協(xié)程詳解

    通過Boost.Coroutine,可以在C++中使用協(xié)程。協(xié)程是其他編程語言的一個特性,通常使用關鍵字yield來表示協(xié)程。在這些編程語言中,yield可以像return一樣使用
    2022-11-11

最新評論

靖边县| 始兴县| 林芝县| 合阳县| 杂多县| 德州市| 沽源县| 东乡县| 九龙县| 永清县| 乌拉特前旗| 益阳市| 太保市| 彭水| 徐州市| 古丈县| 稷山县| 乌拉特后旗| 遵义市| 贵州省| 准格尔旗| 加查县| 慈利县| 武隆县| 阳新县| 修水县| 和林格尔县| 绥棱县| 滦南县| 镇远县| 玉林市| 高淳县| 云龙县| 惠州市| 天台县| 肃南| 宜良县| 理塘县| 长子县| 个旧市| 库伦旗|