【问题标题】:Using an array of function pointer instead of switch使用函数指针数组代替开关
【发布时间】:2020-03-05 00:14:30
【问题描述】:

使用函数指针数组和switch有什么区别吗? 我写了这样的代码

// Declaritons of add-substract-multiply funcitons

void (*fun_ptr_arr[])(int, int) = {add, subtract, multiply}; 
unsigned int ch, a = 15, b = 10; 

printf("Enter Choice: 0 for add, 1 for subtract and 2 "
        "for multiply\n"); 
scanf("%d", &ch); 

if (ch > 2) return 0; 

(*fun_ptr_arr[ch])(a, b); 

我想知道这里的代码或使用开关会更好吗? (就性能而言)

【问题讨论】:

  • 在性能方面?您必须对其进行基准测试。我的猜测是,性能差异将比 IO 绑定 printfscanf 调用的运行时间低几个数量级。一般fun_ptr_arr[ch]有固定的runtime,switch可以编译成跳转表,也有固定的runtime。
  • 请注意,您检查ch 是否大于2,但您也应该检查它是否小于0(或者在您应该使用无符号整数时停止使用有符号整数!)
  • 你没有在这里检查负值。如果你这样做了,那么它们在外部行为上都是 equal 的,这取决于编译器的实现。见as-if rule
  • 您可能不应该打扰,差异很可能很小,不值得担心。而且编译器现在很聪明,它们可能会进行您甚至无法想象的优化。

标签: c performance pointers switch-statement


【解决方案1】:

带有相邻数字的switch 语句通常在内部优化为函数指针查找表。

从历史上看,编译器在这方面做得很差,而函数指针表在过去总是更快。如今,性能不应该成为任何一个版本的论据。事实上,手动函数指针表的一个缺点是编译器将无法内联函数,否则在优化 switch 时可以这样做。

所以你不应该使用函数指针版本,因为它更快/更慢,而是因为它可以提高代码的可读性和维护性。

例如,在实现有限状态机时使用此类函数指针表是一种常见的做法。另一方面,复杂的switch 语句难以阅读,并且语法存在各种怪癖,例如缺少break 错误等。

最后,如果你改成这样写,你可以提高代码的可读性:

typedef void operation_t (int op1, int op2);  // function type

operation_t* const op_array[] = {add, subtract, multiply}; // read-only function pointer table

op_array[i](a, b); // call specific function

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-15
    • 2015-08-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多