中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C語言柔性數組怎么使用

發布時間:2023-04-19 11:17:27 來源:億速云 閱讀:89 作者:iii 欄目:開發技術

今天小編給大家分享一下C語言柔性數組怎么使用的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

一、前言

仔細觀察下面的代碼,有沒有看出哪里不對勁?

struct S
{
    int i;
    double d;
    char c;
    int arr[];
};

還有另外一種寫法:

struct S
{
    int i;
    double d;
    char c;
    int arr[0];
};

你應該一眼就看到了,結構體的最后一個成員數組的寫法是int arr[];或者是int arr[0],這兩種寫法是等價的,意思是這個數組的大小是不確定的、未知的、可以變化的。

C99允許這種特殊的結構體存在。這樣的結構體滿足下面兩個條件:

1.最后一個成員變量是一個大小可以變化的數組。

2.這個成員數組前面至少有另外一個成員變量。

我們稱這個大小可以變化的成員數組為柔性數組。

注意,柔性數組不能是結構體里唯一一個成員,下面的代碼是不允許的:

struct S
{
    int arr[0];
};

這篇文章里,我將重點探討柔性數組的用法、內存分布以及和優勢。

二、柔性數組的用法

我不建議在棧上直接定義有柔性數組的結構體,也就是這么寫:

struct S s;

因為柔性數組的大小是可以變化的,我建議在堆上申請空間,采取動態內存管理的方法,這樣就能發揮出柔性數組大小可以改變的優勢。

假設我們使用malloc()函數來開辟空間,一開始應該malloc出多大的空間呢?要回答這個問題,首先我們要知道sizeof(struct S)是多少。

事實上,sizeof(struct S)計算出來的結果是該結構體不考慮柔性數組的大小。如果我們想要給柔性數組開辟空間,malloc出來的大小應該是sizeof(struct S)加上柔性數組的大小。

假設這個柔性數組在結構體中的聲明是int arr[0];,我想給這個數組的大小是40個字節,這樣這個數組就能存儲10個int,那么一開始malloc的大小就應該是sizeof(struct S)+10*sizeof(int),具體的例子如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(int));
	if (ps == NULL)
	{
		printf("malloc()->%s\n", strerror(errno));
		return 1;
	}

	return 0;
}

該結構體中的i,d,c等變量可以正常使用。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(int));
	if (ps == NULL)
	{
		printf("malloc()->%s\n", strerror(errno));
		return 1;
	}

	ps->i = 10;
	ps->d = 3.14;
	ps->c = 'F';

	return 0;
}

柔性數組也可以像正常的數組一樣訪問,比如把1~10放進去。注意此時這個數組的容量是10個int,不能越界訪問。使用的例子如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(int));
	if (ps == NULL)
	{
		printf("malloc()->%s\n", strerror(errno));
		return 1;
	}

	ps->i = 10;
	ps->d = 3.14;
	ps->c = 'F';

	for (int i = 0; i < 10; i++)
	{
		ps->arr[i] = i + 1;
	}

	for (int i = 0; i < 10; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	printf("\n");

	return 0;
}

我們還可以對柔性數組擴容,如果我們想讓這個柔性數組的容量是20個int,整個結構體的新的大小就是sizeof(struct S)+20*sizeof(int),因為sizeof(struct S)是不考慮柔性數組的大小時計算的結構體大小。只需要對ps進行realloc就行了。實現代碼如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(int));
	if (ps == NULL)
	{
		printf("malloc()->%s\n", strerror(errno));
		return 1;
	}

	ps->i = 10;
	ps->d = 3.14;
	ps->c = 'F';

	for (int i = 0; i < 10; i++)
	{
		ps->arr[i] = i + 1;
	}

	for (int i = 0; i < 10; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	printf("\n");

	struct S* tmp = (struct S*)realloc(ps, sizeof(struct S) + 20 * sizeof(int));
	if (tmp == NULL)
	{
		printf("realloc()->%s\n", strerror(errno));
		return 1;
	}
	else
	{
		ps = tmp;
	}

	return 0;
}

擴容后的柔性數組的空間更大了,我們可以把11~20都放進去。實現代碼如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(int));
	if (ps == NULL)
	{
		printf("malloc()->%s\n", strerror(errno));
		return 1;
	}

	ps->i = 10;
	ps->d = 3.14;
	ps->c = 'F';

	for (int i = 0; i < 10; i++)
	{
		ps->arr[i] = i + 1;
	}

	for (int i = 0; i < 10; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	printf("\n");

	struct S* tmp = (struct S*)realloc(ps, sizeof(struct S) + 20 * sizeof(int));
	if (tmp == NULL)
	{
		printf("realloc()->%s\n", strerror(errno));
		return 1;
	}
	else
	{
		ps = tmp;
	}

	for (int i = 10; i < 20; i++)
	{
		ps->arr[i] = i + 1;
	}
	
	for (int i = 0; i < 20; i++)
	{
		printf("%d ", ps->arr[i]);
	}

	return 0;
}

當然最后別忘了free掉ps,否則會導致內存泄漏。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(int));
	if (ps == NULL)
	{
		printf("malloc()->%s\n", strerror(errno));
		return 1;
	}

	ps->i = 10;
	ps->d = 3.14;
	ps->c = 'F';

	for (int i = 0; i < 10; i++)
	{
		ps->arr[i] = i + 1;
	}

	for (int i = 0; i < 10; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	printf("\n");

	struct S* tmp = (struct S*)realloc(ps, sizeof(struct S) + 20 * sizeof(int));
	if (tmp == NULL)
	{
		printf("realloc()->%s\n", strerror(errno));
		return 1;
	}
	else
	{
		ps = tmp;
	}

	for (int i = 10; i < 20; i++)
	{
		ps->arr[i] = i + 1;
	}
	
	for (int i = 0; i < 20; i++)
	{
		printf("%d ", ps->arr[i]);
	}

	free(ps);
	ps = NULL;

	return 0;
}

對于柔性數組的使用,在上面的例子中,可以總結出幾個要點:

1.malloc出來的大小是sizeof(struct S)加上柔性數組的大小,calloc同理。

2.擴容時realloc出來的新大小也是sizeof(struct S)加上柔性數組的新大小。

3.每次使用malloc和realloc等函數時,需要檢查返回值,否則可能導致對NULL指針的解引用(這點是動態內存管理的常識了)。

4.一定要記得柔性數組的容量是多少,不要越界訪問了,空間不夠記得擴容。

5.記得free,防止內存泄漏。

三、柔性數組的內存分布

柔性數組是結構體的一個成員數組,在前面的例子中,整個結構體都是在堆上malloc出來的。此時,整個結構體都存儲在堆上的一塊連續的空間里,包括前面幾個成員變量i,d,c和柔性數組arr。也就是這樣:

C語言柔性數組怎么使用

只不過數組arr的大小是可以改變的,所以叫“柔性數組”。

有些朋友可能會說了,我不需要柔性數組也能實現類似這樣的效果呀!我在結構體里存一個指針,指向一塊malloc出來的空間,這塊空間也是堆上的,可以動態管理。也就是說,像下面這樣定義結構體:

struct S
{
    int i;
    double d;
    char c;
    int* arr;
};

這樣似乎還簡單一點,先malloc出一個struct S出來,malloc的大小就是sizeof(struct S),像這樣:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S));
	if (ps == NULL)
	{
		printf("malloc()->%s\n", strerror(errno));
		return 1;
	}

	return 0;
}

然后再malloc出10個int的大小出來,用結構體中的arr指針來管理這塊空間,像這樣:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S));
	if (ps == NULL)
	{
		printf("malloc()->%s\n", strerror(errno));
		return 1;
	}

	ps->arr = (int*)malloc(10 * sizeof(int));
	if (ps->arr == NULL)
	{
		printf("2: malloc()->%s\n", strerror(errno));
		return 1;
	}

	return 0;
}

此時arr就可以當成一個數組來使用了,比如把1~10放進去。同樣還是要注意不要越界訪問。示例代碼如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S));
	if (ps == NULL)
	{
		printf("malloc()->%s\n", strerror(errno));
		return 1;
	}

	ps->arr = (int*)malloc(10 * sizeof(int));
	if (ps->arr == NULL)
	{
		printf("2: malloc()->%s\n", strerror(errno));
		return 1;
	}

	for (int i = 0; i < 10; i++)
	{
		ps->arr[i] = i + 1;
	}
	
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	printf("\n");

	return 0;
}

你如果覺得空間不夠,還可以擴容。比如,你可以把結構體中的arr進行realloc,新的大小能存放20個int。示例代碼如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S));
	if (ps == NULL)
	{
		printf("malloc()->%s\n", strerror(errno));
		return 1;
	}

	ps->arr = (int*)malloc(10 * sizeof(int));
	if (ps->arr == NULL)
	{
		printf("2: malloc()->%s\n", strerror(errno));
		return 1;
	}

	for (int i = 0; i < 10; i++)
	{
		ps->arr[i] = i + 1;
	}
	
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	printf("\n");

	int* tmp = (int*)realloc(ps->arr, 20 * sizeof(int));
	if (tmp == NULL)
	{
		printf("realloc()->%s\n", strerror(errno));
		return 1;
	}
	else
	{
		ps->arr = tmp;
	}

	return 0;
}

此時,你就可以把11~20也放進去。實現代碼如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S));
	if (ps == NULL)
	{
		printf("malloc()->%s\n", strerror(errno));
		return 1;
	}

	ps->arr = (int*)malloc(10 * sizeof(int));
	if (ps->arr == NULL)
	{
		printf("2: malloc()->%s\n", strerror(errno));
		return 1;
	}

	for (int i = 0; i < 10; i++)
	{
		ps->arr[i] = i + 1;
	}

	for (int i = 0; i < 10; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	printf("\n");

	int* tmp = (int*)realloc(ps->arr, 20 * sizeof(int));
	if (tmp == NULL)
	{
		printf("realloc()->%s\n", strerror(errno));
		return 1;
	}
	else
	{
		ps->arr = tmp;
	}

	for (int i = 10; i < 20; i++)
	{
		ps->arr[i] = i + 1;
	}

	for (int i = 0; i < 20; i++)
	{
		printf("%d ", ps->arr[i]);
	}

	return 0;
}

最后別忘了把arr和ps都free掉,而且順序不能錯了。如果你先free掉了ps,結構體就沒了,里面的arr就成為了野指針,內存就泄露了。實現代碼如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S));
	if (ps == NULL)
	{
		printf("malloc()->%s\n", strerror(errno));
		return 1;
	}

	ps->arr = (int*)malloc(10 * sizeof(int));
	if (ps->arr == NULL)
	{
		printf("2: malloc()->%s\n", strerror(errno));
		return 1;
	}

	for (int i = 0; i < 10; i++)
	{
		ps->arr[i] = i + 1;
	}

	for (int i = 0; i < 10; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	printf("\n");

	int* tmp = (int*)realloc(ps->arr, 20 * sizeof(int));
	if (tmp == NULL)
	{
		printf("realloc()->%s\n", strerror(errno));
		return 1;
	}
	else
	{
		ps->arr = tmp;
	}

	for (int i = 10; i < 20; i++)
	{
		ps->arr[i] = i + 1;
	}

	for (int i = 0; i < 20; i++)
	{
		printf("%d ", ps->arr[i]);
	}

	free(ps->arr);
	ps->arr = NULL;
	free(ps);
	ps = NULL;

	return 0;
}

那這種實現的內存分布是怎么樣的呢?這個結構體是存儲在堆上的,用ps來管理,結構體里的一個指針arr又指向了堆上的另一塊空間,如下圖:

C語言柔性數組怎么使用

這種實現方式和柔性數組的方式感覺差不多呀!都是在堆上有個結構體,結構體里有個大小可以變化的數組。那為什么非要搞出來個柔性數組的概念呢?那是因為,柔性數組有它獨特的優勢。

四、柔性數組的優勢

前面我們先用柔性數組實現了一種效果,又不使用柔性數組實現了相似的效果,對比兩種實現方式,我們可以做一些總結:

1.使用上:柔性數組malloc了一次,free了一次;不使用柔性數組要malloc兩次,free兩次。柔性數組的使用更加簡單,不容易出錯。如果不使用柔性數組,可能會忘記free掉結構體里的arr指針,導致內存泄漏。

2.效率上:柔性數組的存儲空間是連續的,訪問時效率更高。

所以,雖然有相似的效果,我更推薦使用柔性數組的方式。

以上就是“C語言柔性數組怎么使用”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

都安| 清远市| 汉川市| 泽普县| 都兰县| 屏东县| 中山市| 女性| 罗江县| 松阳县| 内江市| 山阴县| 韶关市| 阳山县| 渭源县| 兴海县| 奎屯市| 游戏| 大庆市| 祁门县| 南充市| 利川市| 迭部县| 崇礼县| 桃园市| 贵定县| 柳州市| 资兴市| 舒兰市| 乐山市| 金门县| 同仁县| 湖口县| 灵丘县| 邛崃市| 炉霍县| 庆阳市| 丽水市| 特克斯县| 汉中市| 寿宁县|