Pis*_*ic 8 c assembly struct arm class
将具有“成员”函数的 C 风格结构与 C++ 类进行比较,试图对 C++ 开销进行建模,我怀疑以下实现通过包含相同数量的指令大致相同。我发现 C 实现在调用“成员”函数时会产生额外的指令。
\nint main()\n{\n\xc2\xa0 \xc2\xa0 uint32_t a;\n\xc2\xa0 \xc2\xa0 rectangle_t r;\n \n /* struct */\n\xc2\xa0 \xc2\xa0 r.set(2,3, &r);\n /* asm \n ldr \xc2\xa0 \xc2\xa0 r3, [r7, #12]\n adds \xc2\xa0 \xc2\xa0r2, r7, #4\n movs \xc2\xa0 \xc2\xa0r1, #3\n movs \xc2\xa0 \xc2\xa0r0, #2\n blx \xc2\xa0 \xc2\xa0 r3\n */\n\n\xc2\xa0 \xc2\xa0 a = r.getArea(&r);\n /* asm \n ldr \xc2\xa0 \xc2\xa0 r3, [r7, #16]\n adds \xc2\xa0 \xc2\xa0r2, r7, #4\n mov \xc2\xa0 \xc2\xa0 r0, r2\n blx \xc2\xa0 \xc2\xa0 r3\n str \xc2\xa0 \xc2\xa0 r0, [r7, #20]\n movs \xc2\xa0 \xc2\xa0r3, #0\n */\n\n /* Class */\n\xc2\xa0 \xc2\xa0 r.set(2, 3);\n /* asm \n adds \xc2\xa0 \xc2\xa0r3, r7, #4\n movs \xc2\xa0 \xc2\xa0r2, #3\n movs \xc2\xa0 \xc2\xa0r1, #2\n mov \xc2\xa0 \xc2\xa0 r0, r3\n bl \xc2\xa0 \xc2\xa0 \xc2\xa0rectangle_t::set(unsigned int, unsigned int)\n */\n\xc2\xa0 \xc2\xa0 a = r.getArea();\n /* asm \n adds \xc2\xa0 \xc2\xa0r3, r7, #4\n mov \xc2\xa0 \xc2\xa0 r0, r3\n bl \xc2\xa0 \xc2\xa0 \xc2\xa0rectangle_t::getArea()\n str \xc2\xa0 \xc2\xa0 r0, [r7, #12]\n movs \xc2\xa0 \xc2\xa0r3, #0\n */\n}\nRun Code Online (Sandbox Code Playgroud)\n为什么在调用 Stuct 'member' 与类成员时会有额外的 ldr 指令?
\n编译器:ARM GCC 12.2.0(Linux)
\n声明:
\ntypedef struct rectangle rectangle_t;\nstruct rectangle\n{\n\xc2\xa0 \xc2\xa0 uint32_t w;\n\xc2\xa0 \xc2\xa0 uint32_t l;\n\xc2\xa0 \xc2\xa0 void (*set)(uint32_t L, uint32_t W, rectangle_t *self);\n\xc2\xa0 \xc2\xa0 uint32_t (*getArea)(rectangle_t *self); \xc2\xa0 \xc2\xa0\n};\nvoid set(uint32_t L, uint32_t W, rectangle_t *self)\n{\n\xc2\xa0 \xc2\xa0 self->w = W;\n\xc2\xa0 \xc2\xa0 self->l = L;\n}\n\nuint32_t getArea(rectangle_t *self)\n{\n\xc2\xa0 \xc2\xa0 return self->l * self->w;\n}\n\nclass rectangle_t\n{\npublic:\xc2\xa0 \xc2\xa0\n\n\xc2\xa0\xc2\xa0\xc2\xa0 uint32_t w;\n\xc2\xa0 \xc2\xa0 uint32_t l; \xc2\xa0\n\xc2\xa0 \xc2\xa0 void set(uint32_t L, uint32_t W);\n\xc2\xa0 \xc2\xa0 uint32_t getArea();\xc2\xa0\n};\n\nvoid rectangle_t::set(uint32_t L, uint32_t W)\n{\n\xc2\xa0 \xc2\xa0 w = W;\n\xc2\xa0 \xc2\xa0 l = L;\n}\n\nuint32_t rectangle_t::getArea()\n{\n\xc2\xa0 \xc2\xa0 return l * w;\n}\nRun Code Online (Sandbox Code Playgroud)\n
在 C++ 中,我们可以声明函数类型的结构和/或类成员,并且在给定类的实例的情况下,这些函数变得可访问。
\n但是,在 C 中,我们不能拥有函数类型的字段,因此,您所做的是函数指针。 \xc2\xa0 因此,这些字段是真正的变量\xe2\x80\x94处的实例变量 \xe2\x80 \x94 任何人都可以动态分配给它,这就是开销的来源(必须查阅变量的值,除非编译器可以看到优化;像任何字段变量一样,对于同一结构的不同实例也可以是不同的值).\xc2\xa0 请注意,您还没有在必须执行的某处显示函数指针 \xe2\x80\x94 的初始化r.set = set; r.getArea = getArea;为每个单独的结构实例执行的地方显示函数指针 \xe2\x80\x94 的初始化,否则根据所使用的存储,您将得到垃圾或零对于结构。
为了使 C 代码“某种程度上”等效,请创建函数,而不是函数指针,并且必须在 之外声明它们struct,因此,与 C++ 相比,它们实际上是解绑的。
| 归档时间: |
|
| 查看次数: |
149 次 |
| 最近记录: |