如何定義一個自帶數據區的結構體:三種數據結構體的比較


先看如下三個結構體的定義

這三個結構體的前三個成員都相同,前兩個成員只是為了充個數,從而讓我們定義的struct看上去真的像個結構體,一個是char類型,一個是int類型。最后一個也是int類型,iDataLen用於記錄結構體自帶數據的長度,pData指向的就是我們“認為”的數據區。

// 結構體1
typedef struct data_node1{
	char	cDummy;			
	int	iDummy;
	int	iDataLen;
	char*	pData;
}DATA_NODE1;
// 結構體2
typedef struct data_node2{
	char	cDummy;
	int	iDummy;
	int	iDataLen;
	char	pData[1];
}DATA_NODE2;
// 結構體3
typedef struct data_node3{
	char	cDummy;
	int	iDummy;
	int	iDataLen;
	char*	data(){
		return (char*)(this+1);
	}
}DATA_NODE3;

再寫代碼打印三個數據結構的信息

首先顯示結構體的大小,前兩個結構體是16字節,最后一個結構體是12字節,這個好理解,最后一個結構體中缺少一個成員變量。
說明一下:cDummy雖然是一個char類型,但由於結構體按照最大成員變量的size進行對齊,即使cDummy只需要個單室套,但計算機還是給它分了個三居室。
打個比方:如果你和吳亦凡在同一個struct中,那么你的size也會和“吳簽”對齊的,計算機的世界就是這么平等。
在該函數中我們開辟三個256字節的內存塊,並讓其分別指向三個結構體,從而觀察pData到底指向哪里。

#define INT_DATA_SIZE	256
void TestStruct()
{
	// 獲取結構體的大小
	int iDNSize1 = sizeof(DATA_NODE1);
	int iDNSize2 = sizeof(DATA_NODE2);
	int iDNSize3 = sizeof(DATA_NODE3);

	printf("sizeof(DATA_NODE1) = %d\r\n", iDNSize1);
	printf("sizeof(DATA_NODE2) = %d\r\n", iDNSize2);
	printf("sizeof(DATA_NODE3) = %d\r\n", iDNSize3);

	// 分配三塊內存,並初始化為0
	char* pData1 = (char*)malloc(INT_DATA_SIZE);
	memset(pData1, 0, INT_DATA_SIZE);
	char* pData2 = (char*)malloc(INT_DATA_SIZE);
	memset(pData2, 0, INT_DATA_SIZE);
	char* pData3 = (char*)malloc(INT_DATA_SIZE);
	memset(pData3, 0, INT_DATA_SIZE);

	// 將三塊內存指向對應的結構體
	DATA_NODE1* pDN1 = (DATA_NODE1*)pData1;
	DATA_NODE2* pDN2 = (DATA_NODE2*)pData2;
	DATA_NODE3* pDN3 = (DATA_NODE3*)pData3;

	// 打印結構體1的數據
	
	printf("DATA_NODE1       : address = 0x%08x\r\n", pDN1);
	printf("  pDN1->cDummy   : address = 0x%08x, value = %d\r\n", &pDN1->cDummy, pDN1->cDummy);
	printf("  pDN1->iDummy   : address = 0x%08x, value = %d\r\n", &pDN1->iDummy, pDN1->iDummy); 
	printf("  pDN1->iDataLen : address = 0x%08x, value = %d\r\n", &pDN1->iDataLen, pDN1->iDataLen);
	printf("  pDN1->pData    : address = 0x%08x, poiter address = 0x%08x\r\n\r\n", &(pDN1->pData), pDN1->pData);
		

	// 打印結構體2的數據
	int iSizeStruct2 = pDN2->pData - (char*)pDN2;
	pDN2->iDataLen = INT_DATA_SIZE - iSizeStruct2;
	printf("DATA_NODE2       : address = 0x%08x\r\n", pDN2);
	printf("  pDN2->cDummy   : address = 0x%08x, value = %d\r\n", &pDN2->cDummy, pDN2->cDummy);
	printf("  pDN2->iDummy   : address = 0x%08x, value = %d\r\n", &pDN2->iDummy, pDN2->iDummy); 
	printf("  pDN2->iDataLen : address = 0x%08x, value = %d\r\n", &pDN2->iDataLen, pDN2->iDataLen);
	printf("  pDN2->pData    : address = 0x%08x, poiter address = 0x%08x\r\n\r\n", &(pDN2->pData), pDN2->pData);

	// 打印結構體3的數據
	int iSizeStruct3 = pDN3->data() - (char*)pDN3;
	pDN3->iDataLen = INT_DATA_SIZE - iSizeStruct3;
	printf("DATA_NODE3       : address = 0x%0x\r\n", pDN3);
	printf("  pDN3->cDummy   : address = 0x%0x, value = %d\r\n", &pDN3->cDummy, pDN3->cDummy);
	printf("  pDN3->iDummy   : address = 0x%0x, value = %d\r\n", &pDN3->iDummy, pDN3->iDummy); 
	printf("  pDN3->iDataLen : address = 0x%0x, value = %d\r\n", &pDN3->iDataLen, pDN3->iDataLen);
	printf("  pDN3->data()   : address = 0x%0x\r\n\r\n", pDN3->data());

	free(pData1);
	free(pData2);
	free(pData3);

}

運行結果如圖:

在這里插入圖片描述

最后看三個結構體在內存中的顯示

為了直觀表達結構體的內存,我們假設三個結構體初始地址均為0x10000000。

結構體1
在這里插入圖片描述
結構體2
在這里插入圖片描述
結構體3
在這里插入圖片描述

顯然,后兩種方式可以實現數據區與結構體有機的結合在一起。那么這種定義的應用場景在哪呢?就舉一個IP數據報文的例子吧。
在這里插入圖片描述


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM