先看如下三個結構體的定義
這三個結構體的前三個成員都相同,前兩個成員只是為了充個數,從而讓我們定義的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數據報文的例子吧。

