【问题标题】:How expensive are NULL pointer arguments?NULL 指针参数有多贵?
【发布时间】:2012-08-13 14:45:52
【问题描述】:

在使用 C(++) (AVR-Gcc) 在嵌入式系统上实现菜单时,我最终得到了带有参数的 void 函数指针,并且通常会使用它们。

// void function prototype
void (*auxFunc)(char *);

在某些情况下(实际上不少),函数实际上不需要参数,所以我会这样做:

if (something)    doAuxFunc(NULL);

我知道我可以重载到不同的函数类型,但实际上我正在尝试不这样做,因为我正在实例化多个对象并希望保持它们轻巧。

使用 NULL 指针调用多个函数(当它们用于实际指针时)是否比实现更多函数原型更糟糕?

【问题讨论】:

  • 分析器说什么?
  • 为什么你认为重载很“重”?
  • @KerrekSB 主要是因为会有(相对)很多对象持有这些,并且空间在嵌入式系统上很有价值。在这种情况下,菜单更像是项目主要功能的辅助部分。
  • @falro: “主要是因为会有(相对)许多对象持有这些” -- 你确实意识到重载会创建两个实例而不是一个,即使对于一个百万物体?并不是每个对象都拥有可执行代码的新副本。
  • @Damon 啊,是的,你是对的。没想到这一点。

标签: c++ c performance embedded avr-gcc


【解决方案1】:

即使在微控制器上检查 NULL 也是非常小的开销 - 与 0 的比较应该是闪电般的快。如果你重载了几个函数,你会为了(非常轻微的)性能改进而牺牲可读性。让 GCC 的优化器来做它的事情,它非常擅长:)

【讨论】:

    【解决方案2】:

    查看反汇编,它应该生成一个空(零)作为第一个参数传递,它要么烧录寄存器或堆栈位置,如果它烧录一个寄存器,那么如果调用函数急需寄存器。 (如果函数为了实现调用约定而急需寄存器,则仅使用函数调用可能会花费您推送和弹出的费用)。

    因此可能会有成本,但可能不足以改变您做事的方式。

    【讨论】:

      【解决方案3】:

      检查0 真的很便宜,重载更便宜,因为在编译时决定选择哪个函数。

      但是,如果您认为您的接口因重载而变得过于复杂并且您的函数很小,您应该将其声明为 inline 并将其放在标题中。 Checkig for 0 然后可以很容易地被任何体面的现代编译器优化掉。

      【讨论】:

      • 因为这是一个嵌入式系统的解决方案,内联会导致使用更多的代码内存,在这种情况下也很昂贵。
      • @syplex:这在很大程度上取决于函数调用和清理的大小。内联可以节省空间。当合理的优化器可以消除不需要的指令时尤其如此。一个常见的简单示例是 Foo::getBar 方法,它提供对 Foo 中的 Bar 成员的只读访问。这可能最终成为一个简单的指针偏移计算,甚至可以与其他偏移计算折叠。
      • gcc 现在具有进行部分内联的功能。基本上它将根据所有参数创建一个函数核心,然后内联可以不断传播的部分。这没有太多的大小开销。
      【解决方案4】:

      我认为每种方法的“权衡”都非常低,但现在是为自己做基准测试的时候了。如果你这样做,请发布一些结果:)

      【讨论】:

        猜你喜欢
        • 2015-11-22
        • 1970-01-01
        • 2011-12-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-01
        • 1970-01-01
        相关资源
        最近更新 更多