涉及到内存中结构体优化对齐以及一些函数对于内存的处理逻辑。由于我不是科班出生,理解的不够深入,有问题的地方希望大神们多多指出。 有这样的一个结构体 typedef struct { int head; int size; //指明整个包的长度 char reply; char data[0]; } packet; 和#define offsetof(type, element) ((int)&((type *)0)->element) static inline size_t packet_data_len(packet* cmd) { assert(cmd); return cmd->size - offsetof(packet, data); } 测试函数 int main() { char szBuf[1024]; char recvdata[1024]; char *somedata = "tesx data"; packet* pSend = malloc(sizeof(packet) + 20); memset(pSend, 0x00, sizeof(packet) + 20); pSend->size = sizeof(packet)+20; memcpy(pSend->data, somedata, 20); printf("somedata[%s]\n", somedata); printf("pSend->data[%s]\n", pSend->data); printf("-------------------------------------------------------\n"); memset(szBuf, 0x00, sizeof(szBuf)); memcpy(szBuf, pSend, sizeof(packet)+20); printf("打印通过memcpy拷贝后的内容\n"); printf("packet length[%d]\n", sizeof(packet)); printf("szBuf+12[%s]\n", szBuf + sizeof(packet)); printf("szBuf+9[%s]\n", szBuf + 9); printf("-------------------------------------------------------\n"); printf("packet length[%d]\n", sizeof(packet)); printf("offset length[%d]\n", offsetof(packet, data)); printf("data length[%d]\n", packet_data_len((packet*)szBuf)); printf("data start addr offset[%d]\n", ((packet*)szBuf)->data-szBuf); printf("data[0][%c]\n", ((packet*)szBuf)->data[0]); printf("data[%s]\n", szBuf+sizeof(packet)); printf("data[%s]\n", szBuf+9); memcpy(recvdata, ((packet*)szBuf)->data, packet_data_len((packet*)szBuf)); printf("-------------------------------------------------------\n"); printf("print[%s]\n", recvdata); return 0; }
输出结果: somedata[tesx data] pSend->data[tesx data] ------------------------------------------------------- 打印通过memcpy拷贝后的内容 packet length[12] szBuf+12[x data] szBuf+9[tesx data] ------------------------------------------------------- packet length[12] offset length[9] data length[23] data start addr offset[9] data[0][t] data[x data] data[tesx data] ------------------------------------------------------- print[tesx data] 个人得出的结论: 步骤一:按照多余结构20个字节长度开辟内存空间,然后对结构体里的内容进行赋值。最后通过结构体内成员对象进行打印,能正常的打印出赋值进去的内容。 步骤二:在进行第一步之后,用memcpy()拷贝步骤一中结构体大小加上20个字节的长度,我用sizeof()获取了结构体的大小,同时用字符数组名+结构体的长度作为起始位置进行字符串打印,得到的结果是从x字符开始打印。而我用字符数组名+结构体成员自身长度之和作为起始位置进行字符串打印,得到的结果却是完整的字符串。 步骤三:用宏取结构体data成员的位置偏移量为9,返回数据长度的方法获取的数据的长度为23,以及通过数据的起始位置到结构体起始位置的差值也为9,同时用该位置去打印数据能获取到完整的数据。 由此可见,sizeof()在计算的时候,是数据对齐了之后的整体长度,而在进行memcpy()拷贝的时候,内部是不是做了何种处理,没有保留补充对齐的那部分空间。 当然,如果我们本身定义的结构体就是对齐的,则不会存在这中情况,如 typedef struct { int head; int size; //指明整个包的长度 char reply; char reply1; char reply2; char reply3; char data[0]; } packet;
有兴趣的朋友可以试一下。 注意:特别是在网络传输处理以及其他的处理过程中特别需要注意,不然会出现千奇百怪的问题。
