gpt4 book ai didi

c - C 嵌入式软件中的查找表与开关

转载 作者:太空狗 更新时间:2023-10-29 16:21:07 25 4
gpt4 key购买 nike

在另一个线程中,有人告诉我,就速度和紧凑性而言,开关 可能比查找表 更好。

所以我想了解这之间的区别:

查找表

static void func1(){}
static void func2(){}

typedef enum
{
FUNC1,
FUNC2,
FUNC_COUNT
} state_e;

typedef void (*func_t)(void);

const func_t lookUpTable[FUNC_COUNT] =
{
[FUNC1] = &func1,
[FUNC2] = &func2
};

void fsm(state_e state)
{
if (state < FUNC_COUNT)
lookUpTable[state]();
else
;// Error handling
}

还有这个:

切换

static void func1(){}
static void func2(){}

void fsm(int state)
{
switch(state)
{
case FUNC1: func1(); break;
case FUNC2: func2(); break;
default: ;// Error handling
}
}

我认为查找表更快,因为编译器会尽可能将 switch 语句转换为跳转表。由于这可能是错误的,我想知道为什么!

感谢您的帮助!

最佳答案

由于我是评论的原作者,我必须添加一个您在问题中未提及的非常重要的问题。也就是说,原来是关于嵌入式系统的。假设这是一个典型的带有集成闪存的裸机系统,它与我将重点关注的 PC 有非常重要的区别。

此类嵌入式系统通常具有以下限制。

  • 没有 CPU 缓存。
  • Flash 需要更高(即 >ca. 32MHz)CPU 时钟的等待状态。实际比例取决于芯片设计、低功耗/高速工艺、工作电压等。
  • 为了隐藏等待状态,Flash 具有比 CPU 总线更宽的读取线。
  • 这只适用于带指令预取的线性代码。
  • 数据访问会干扰指令预取或在完成前停止。
  • Flash 可能有一个非常小的内部指令缓存。
  • 如果有的话,还有一个更小的数据缓存。
  • 较小的缓存会导致更频繁的垃圾处理(替换之前已被其他时间使用的先前条目)。

例如STM32F4xx 在 150MHz/3.3V 下读取 128 位(4 个字)需要 6 个时钟。因此,如果需要数据访问,很有可能会为要获取的所有数据增加超过 12 个时钟的延迟(涉及额外的周期)。

假设紧凑的状态代码,对于实际问题,这对该体系结构(Cortex-M4)有以下影响:

  • 查找表:读取函数地址是一种数据访问。具有上述所有含义。
  • 开关 otoh 使用特殊的“查表”指令,该指令使用紧跟在指令后面的代码空间数据。所以第一个条目可能已经预取。其他条目不会破坏预取。访问也是代码访问,因此数据进入闪存的指令缓存。

另请注意,switch 不需要函数,因此编译器可以充分优化代码。这对于查找表是不可能的。至少不需要函数入口/导出的代码。


由于上述和其他因素,估计很难说。这在很大程度上取决于您的平台和代码结构。但是假设上面给出的系统,切换很可能更快(顺便说一句,也更清晰)。

关于c - C 嵌入式软件中的查找表与开关,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35838849/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com