结构体(Struct)内部成员字节对齐问题
【生活经历分享】华师国培 华师伴学 合同都是坑 消费者付款后无法退款和华师国培签合同需小心,合同中都是保护华师的条款,没有保护消费者的条款。
收到钱,就算你因对培训质量不满意,也不能退款。因合同消费者维权肯定十分艰难。
华师伴学的授课方式是看录制的视频,不是真人现场教学。是否是您和孩子想要的学习方式?
各位打算报名的,交费要谨慎!
其他人在小红书上发的,转:
深圳市华师国培教育科技有限公司,黑心机构,大家擦亮眼睛,别被骗了,消费欺诈,虚假承诺,签合同各种坑,收到钱了不履行承诺不退款,乱扣费,维权艰难! - 小红书
【说明:欢迎转载!转载请注明出处,且不能修改文章内容。否则,请勿转载!】
一、结构体的成员都是基本数据类型
结构体成员开始地址与数据类型相关,为数据类型长度的整体倍。否则,即使给内存赋值成功,结构体成员变量的值仍然无法改变。
1 typedef struct Tst_Struct_BASIC_T { 2 uint8 member; 3 uint16 member2; 4 }Tst_Struct_BASIC; 5 typedef struct Tst_Struct_BASIC2_T { 6 uint8 member; 7 uint32 member2; 8 }Tst_Struct_BASIC2; 9 typedef struct Tst_Struct_BASIC3_T { 10 uint8 member; 11 float member2; 12 }Tst_Struct_BASIC3; 13 typedef struct Tst_Struct_BASIC4_T { 14 uint8 member; 15 uint8 member2; 16 }Tst_Struct_BASIC4; 1 // 结构体中不同基本数据类型变量地址 2 Tst_Struct_BASIC basic_var = { 0 }; 3 Tst_Struct_BASIC2 basic_var2 = { 0 }; 4 Tst_Struct_BASIC3 basic_var3 = { 0 }; 5 Tst_Struct_BASIC4 basic_var4 = { 0 }; 6 7 TRACE("size of basic_var: %d\n", sizeof(basic_var)); // size of basic_var: 4 8 TRACE("size of basic_var2: %d\n", sizeof(basic_var2)); // size of basic_var2: 8 9 TRACE("size of basic_var3: %d(size of float: %d)\n", sizeof(basic_var3), sizeof(float)); // size of basic_var3: 8(size of float: 4) 10 TRACE("size of basic_var4: %d\n", sizeof(basic_var4)); // size of basic_var4: 2 11 12 BYTE* tst_point = (BYTE*)&basic_var; 13 uint8 value_8b = 11; 14 uint16 value_16b = 22; 15 memcpy(tst_point, &value_8b, sizeof(value_8b)); 16 memcpy(tst_point + 1, &value_16b, sizeof(value_16b)); 17 TRACE("value of struct 1: %d %d\n", basic_var.member, basic_var.member2); // value of struct 1: 11 0 18 memcpy(tst_point + 2, &value_16b, sizeof(value_16b)); 19 TRACE("value of struct 1: %d %d\n", basic_var.member, basic_var.member2); // value of struct 1: 11 22 20 21 BYTE* tst_point2b = (BYTE*)&basic_var2; 22 uint16 value_32b = 33; 23 memcpy(tst_point2b, &value_8b, sizeof(value_8b)); 24 memcpy(tst_point2b + 1, &value_16b, sizeof(value_16b)); 25 TRACE("value of struct 2: %d %d\n", basic_var2.member, basic_var2.member2); // value of struct 2: 11 0 26 memcpy(tst_point2b + 2, &value_16b, sizeof(value_16b)); 27 TRACE("value of struct 2: %d %d\n", basic_var2.member, basic_var2.member2); // value of struct 2: 11 0 28 memcpy(tst_point2b + 4, &value_32b, sizeof(value_32b)); 29 TRACE("value of struct 2: %d %d\n", basic_var2.member, basic_var2.member2); // value of struct 2: 11 33 |
结构体内存示例:

通过 Debug 查看内存与结构体变量的值进行对比:

二、结构体的成员是结构体
子结构体开始地址与子结构体成员类型有关,开始地址为最长类型的整体倍。
typedef struct Tst_Struct_UINT8_T { uint8 member; uint8 member2; uint8 member3; uint8 member4; uint8 member5; uint8 member6; uint8 member7; uint8 member8; }Tst_Struct_UINT8; typedef struct Tst_Struct_UINT16_T { uint16 member; uint16 member2; uint16 member3; uint16 member4; }Tst_Struct_UINT16; typedef struct Tst_Struct_UINT32_T { uint32 member; uint32 member2; }Tst_Struct_UINT32; typedef struct Tst_Struct_UINT64_T { uint64 member; }Tst_Struct_UINT64; typedef struct Tst_Struct_Size_Addr_T { uint8 member; Tst_Struct_UINT8 member8; }Tst_Struct_Size_Addr; typedef struct Tst_Struct_Size_Addr2_T { uint8 member; Tst_Struct_UINT16 member16; }Tst_Struct_Size_Addr2; typedef struct Tst_Struct_Size_Addr3_T { uint8 member; Tst_Struct_UINT32 member32; }Tst_Struct_Size_Addr3; typedef struct Tst_Struct_Size_Addr4_T { uint8 member; Tst_Struct_UINT64 member64; }Tst_Struct_Size_Addr4; 1 // 结构体嵌套时子结构体变量开始地址测试 2 Tst_Struct_Size_Addr tst_addr_1 = { 0 }; 3 Tst_Struct_Size_Addr2 tst_addr_2 = { 0 }; 4 Tst_Struct_Size_Addr3 tst_addr_3 = { 0 }; 5 Tst_Struct_Size_Addr4 tst_addr_4 = { 0 }; 6 7 TRACE("sizeof tst_addr_1: %d\n", sizeof(tst_addr_1)); // sizeof tst_addr_1: 9 8 TRACE("sizeof tst_addr_2: %d\n", sizeof(tst_addr_2)); // sizeof tst_addr_1: 10 9 TRACE("sizeof tst_addr_3: %d\n", sizeof(tst_addr_3)); // sizeof tst_addr_1: 12 10 TRACE("sizeof tst_addr_4: %d\n", sizeof(tst_addr_4)); // sizeof tst_addr_1: 16 11 12 // 子结构体变量首地址,与结构体首地址之差 13 size_t offset1 = (unsigned long long)(&(tst_addr_1.member8)) - (unsigned long long)(&tst_addr_1); 14 size_t offset2 = (unsigned long long)(&(tst_addr_2.member16)) - (unsigned long long)(&tst_addr_2); 15 size_t offset3 = (unsigned long long)(&(tst_addr_3.member32)) - (unsigned long long)(&tst_addr_3); 16 size_t offset4 = (unsigned long long)(&(tst_addr_4.member64)) - (unsigned long long)(&tst_addr_4); 17 TRACE("Addr 08: 0x%x 0x%x %d\n", &tst_addr_1, &(tst_addr_1.member8), offset1); // Addr 08: 0x69cfa258 0x69cfa259 1 18 TRACE("Addr 16: 0x%x 0x%x %d\n", &tst_addr_2, &(tst_addr_2.member16), offset2); // Addr 16: 0x69cfa288 0x69cfa28a 2 19 TRACE("Addr 32: 0x%x 0x%x %d\n", &tst_addr_3, &(tst_addr_3.member32), offset3); // Addr 32: 0x69cfa2b8 0x69cfa2bc 4 20 TRACE("Addr 64: 0x%x 0x%x %d\n", &tst_addr_4, &(tst_addr_4.member64), offset4); // Addr 64: 0x69cfa2e8 0x69cfa2f0 8 21 uint8* tst_point1 = (uint8*)&tst_addr_1; 22 uint8* tst_point2 = (uint8*)&tst_addr_2; 23 uint8* tst_point3 = (uint8*)&tst_addr_3; 24 uint8* tst_point4 = (uint8*)&tst_addr_4; 25 26 // 指向 Tst_Struct_UINT8_T -> uint8 member; 27 uint8 value_08 = 8; 28 uint16 value_16 = 16; 29 uint32 value_32 = 32; 30 uint64 value_64 = 64; 31 memcpy((tst_point1 + 1), &value_08, sizeof(value_08)); 32 if ((uint8)(tst_point1 + 1) == value_08) { 33 TRACE("same to value_08\n"); 34 } 35 memcpy((tst_point2 + 1), &value_16, sizeof(value_16)); 36 if ((uint8)(tst_point2 + 1) == value_16) { 37 TRACE("same to value_16 1 - %d <> %d\n", value_16, tst_addr_2.member16.member); // same to value_16 1 - 16 <> 0 38 } 39 memcpy((tst_point2 + 2), &value_16, sizeof(value_16)); 40 if ((uint8)(tst_point2 + 2) == value_16) { 41 TRACE("same to value_16 2 - %d <> %d\n", value_16, tst_addr_2.member16.member); // same to value_16 2 - 16 <> 16 42 } 43 memcpy((tst_point3 + 1), &value_32, sizeof(value_32)); 44 if ((uint8)(tst_point3 + 1) == value_32) { 45 TRACE("same to value_32 1 - %d <> %d\n", value_32, tst_addr_3.member32.member); // same to value_32 1 - 32 <> 0 46 } 47 memcpy((tst_point3 + 2), &value_32, sizeof(value_32)); 48 if ((uint8)(tst_point3 + 2) == value_32) { 49 TRACE("same to value_32 2 - %d <> %d\n", value_32, tst_addr_3.member32.member); // same to value_32 2 - 32 <> 0 50 } 51 memcpy((tst_point3 + 4), &value_32, sizeof(value_32)); 52 if ((uint8)(tst_point3 + 4) == value_32) { 53 TRACE("same to value_32 3 - %d <> %d\n", value_32, tst_addr_3.member32.member); // same to value_32 3 - 32 <> 32 54 } 55 memcpy((tst_point4 + 1), &value_64, sizeof(value_64)); 56 if ((uint8)(tst_point4 + 1) == value_64) { 57 TRACE("same to value_64 1 - %d <> %d\n", value_64, tst_addr_4.member64.member); // same to value_64 1 - 64 <> 0 58 } 59 memcpy((tst_point4 + 2), &value_64, sizeof(value_64)); 60 if ((uint8)(tst_point4 + 2) == value_64) { 61 TRACE("same to value_64 2 - %d <> %d\n", value_64, tst_addr_4.member64.member); // same to value_64 2 - 64 <> 0 62 } 63 memcpy((tst_point4 + 4), &value_64, sizeof(value_64)); 64 if ((uint8)(tst_point4 + 4) == value_64) { 65 TRACE("same to value_64 3 - %d <> %d\n", value_64, tst_addr_4.member64.member); // same to value_64 3 - 64 <> 0 66 } 67 memcpy((tst_point4 + 8), &value_64, sizeof(value_64)); 68 if ((uint8)(tst_point4 + 8) == value_64) { 69 TRACE("same to value_64 4 - %d <> %d\n", value_64, tst_addr_4.member64.member); // same to value_64 4 - 64 <> 64 70 }
|
结构体&子结构体内存示例:

通过 Debug 查看内存与结构体变量的值进行对比:

测试结构体指针指向内存块,观察结构体的数值,也发现部分中间的内存数值未在结构体中出现。如下图:


浙公网安备 33010602011771号