Line data Source code
1 : /*
2 : * test_cpp_memory_layout.cpp
3 : *
4 : * Jun 15, 2019
5 : * @author Andrey Belomutskiy, (c) 2012-2020
6 : */
7 :
8 : #include "pch.h"
9 :
10 : // in C++ struct is pretty much a class just fields are public by default
11 : struct TestParent {
12 : int field0 = 540;
13 : float field1 = 333.33;
14 : };
15 :
16 : class TestPlainChild: public TestParent {
17 : public:
18 : float getSum();
19 : };
20 :
21 : class TestPlainChildExtraFields: public TestParent {
22 : public:
23 : float field3 = 35555;
24 : float field4 = 45555;
25 : };
26 :
27 :
28 0 : float TestPlainChild::getSum() {
29 0 : return field0 + field1;
30 : }
31 :
32 : class TestChildWithVirtual: public TestParent {
33 : public:
34 0 : virtual float getSumVirtual() {
35 0 : return field0 + field1;
36 : }
37 : };
38 :
39 :
40 4 : TEST(CppMemoryLayout, PlainStruct) {
41 1 : TestPlainChild c;
42 : // validate field initializers just for fun
43 1 : ASSERT_EQ(540, c.field0);
44 1 : ASSERT_NEAR(333.33, c.field1, EPS4D);
45 :
46 1 : ASSERT_EQ(sizeof(c), sizeof(TestParent));
47 :
48 1 : int destimationInt = 1;
49 : // no virtual table since nothing virtual on TestPlainChild
50 1 : memcpy(&destimationInt, &c, 4);
51 1 : ASSERT_EQ(540, destimationInt);
52 :
53 1 : ASSERT_EQ((uintptr_t)&c.field0, (uintptr_t)&c);
54 : }
55 :
56 : static int valueWePointAt;
57 :
58 4 : TEST(CppMemoryLayout, VirtualStruct) {
59 1 : TestChildWithVirtual c;
60 :
61 : // '4' in case of 32 bit target
62 : // '8' in case of 64 bit target
63 1 : int MAGIC_VTABLE_SIZE = sizeof(void*);
64 :
65 : // validate field initializers just for fun
66 1 : ASSERT_EQ(540, c.field0);
67 1 : ASSERT_NEAR(333.33, c.field1, EPS4D);
68 :
69 1 : ASSERT_EQ(sizeof(c), sizeof(TestParent) + MAGIC_VTABLE_SIZE);
70 :
71 :
72 1 : int destimationInt = 1;
73 1 : memcpy(&destimationInt, &c, 4);
74 1 : ASSERT_NE(540, destimationInt);
75 :
76 : // static_cast is smart to skip the vtable, we like static_cast
77 1 : TestParent *parent = static_cast<TestParent*>(&c);
78 1 : ASSERT_EQ((uintptr_t)&c.field0, (uintptr_t)parent);
79 :
80 1 : ASSERT_EQ(MAGIC_VTABLE_SIZE, (uintptr_t)&c.field0 - (uintptr_t)&c);
81 :
82 :
83 : }
84 :
85 4 : TEST(CppMemoryLayout, PlainExtraFieldsStruct) {
86 1 : TestPlainChildExtraFields c;
87 :
88 1 : ASSERT_EQ(sizeof(c), sizeof(TestParent) + 8);
89 :
90 1 : int destimationInt = 1;
91 : // parent fields go first
92 1 : memcpy(&destimationInt, &c, 4);
93 1 : ASSERT_EQ(540, destimationInt);
94 1 : ASSERT_EQ(0, (uintptr_t)&c.field0 - (uintptr_t)&c);
95 : }
96 :
97 4 : TEST(CppMemoryLayout, structSize) {
98 1 : ASSERT_EQ(1, sizeof(adc_channel_e)) << "adc_channel_e enum size";
99 1 : ASSERT_EQ(1, sizeof(pin_input_mode_e)) << "pin_input_mode_e enum size";
100 1 : ASSERT_EQ(1, sizeof(pin_output_mode_e)) << "pin_output_mode_e enum size";
101 1 : ASSERT_EQ(2, sizeof(brain_pin_e)) << "brain_pin_e enum size";
102 1 : ASSERT_EQ(12, sizeof(air_pressure_sensor_config_s));
103 1 : ASSERT_EQ(TOTAL_CONFIG_SIZE, sizeof(persistent_config_s));
104 : }
|