NULL 指针参数有多贵?
Posted
技术标签:
【中文标题】NULL 指针参数有多贵?【英文标题】:How expensive are NULL pointer arguments? 【发布时间】:2012-08-13 14:45:52 【问题描述】:在使用 C(++) (AVR-Gcc) 在嵌入式系统上实现菜单时,我最终得到了带有参数的 void 函数指针,并且通常会使用它们。
// void function prototype
void (*auxFunc)(char *);
在某些情况下(实际上不少),函数实际上不需要参数,所以我会这样做:
if (something) doAuxFunc(NULL);
我知道我可以重载到不同的函数类型,但实际上我正在尝试不这样做,因为我正在实例化多个对象并希望保持它们轻巧。
使用 NULL 指针调用多个函数(当它们用于实际指针时)是否比实现更多函数原型更糟糕?
【问题讨论】:
分析器说什么? 为什么你认为重载很“重”? @KerrekSB 主要是因为会有(相对)很多对象持有这些,并且空间在嵌入式系统上很有价值。在这种情况下,菜单更像是项目主要功能的辅助部分。 @falro: “主要是因为会有(相对)许多对象持有这些” -- 你确实意识到重载会创建两个实例而不是一个,即使对于一个百万物体?并不是每个对象都拥有可执行代码的新副本。 @Damon 啊,是的,你是对的。没想到这一点。 【参考方案1】:即使在微控制器上检查 NULL 也是非常小的开销 - 与 0 的比较应该是闪电般的快。如果你重载了几个函数,你会为了(非常轻微的)性能改进而牺牲可读性。让 GCC 的优化器来做它的事情,它非常擅长:)
【讨论】:
【参考方案2】:查看反汇编,它应该生成一个空(零)作为第一个参数传递,它要么烧录寄存器或堆栈位置,如果它烧录一个寄存器,那么如果调用函数急需寄存器。 (如果函数为了实现调用约定而急需寄存器,则仅使用函数调用可能会花费您推送和弹出的费用)。
因此可能会有成本,但可能不足以改变您做事的方式。
【讨论】:
【参考方案3】:检查0
真的很便宜,重载更便宜,因为在编译时决定选择哪个函数。
但是,如果您认为您的接口因重载而变得过于复杂并且您的函数很小,您应该将其声明为 inline
并将其放在标题中。 Checkig for 0
然后可以很容易地被任何体面的现代编译器优化掉。
【讨论】:
因为这是一个嵌入式系统的解决方案,内联会导致使用更多的代码内存,在这种情况下也很昂贵。 @syplex:这在很大程度上取决于函数调用和清理的大小。内联可以节省空间。当合理的优化器可以消除不需要的指令时尤其如此。一个常见的简单示例是Foo::getBar
方法,它提供对 Foo 中的 Bar 成员的只读访问。这可能最终成为一个简单的指针偏移计算,甚至可以与其他偏移计算折叠。
gcc 现在具有进行部分内联的功能。基本上它将根据所有参数创建一个函数核心,然后内联可以不断传播的部分。这没有太多的大小开销。【参考方案4】:
我认为每种方法的“权衡”都非常低,但现在是为自己做基准测试的时候了。如果你这样做,请发布一些结果:)
【讨论】:
以上是关于NULL 指针参数有多贵?的主要内容,如果未能解决你的问题,请参考以下文章