使用两个名称在C中调用相同函数的首选方法

Jos*_*hua 17 c embedded function

我知道至少有三种流行的方法可以使用多个名称来调用相同的函数.我实际上没有听说有人为此目的使用第四种方法.

1).可以使用#defines:

int my_function (int);


#define my_func my_function
Run Code Online (Sandbox Code Playgroud)

要么

#define my_func(int (a)) my_function(int (a))
Run Code Online (Sandbox Code Playgroud)

2).嵌入式函数调用是另一种可能性

int my_func(int a) {
    return my_function(a);
}
Run Code Online (Sandbox Code Playgroud)

3).在链接器中使用弱别名:

int my_func(int a) __attribute__((weak, alias("my_function")));
Run Code Online (Sandbox Code Playgroud)

4).功能指针:

int (* const my_func)(int) = my_function;
Run Code Online (Sandbox Code Playgroud)

我需要多个名称的原因是数学库具有相同方法的多个实现.

例如,我需要一种有效的方法来计算标量浮点数的平方根.所以我可以使用math.h的sqrt().这不是很有效.所以我写了一两个其他方法,比如使用牛顿方法.问题是每种技术在某些处理器上更好(在我的情况下是微控制器).所以我希望编译过程选择最好的方法.

我认为这意味着最好使用宏或弱别名,因为这些技术可以很容易地在头文件中的几个#ifdef语句中进行分组.这简化了维护(相对).也可以使用函数指针,但它必须在源文件中,头文件中的常规函数​​的extern声明.

您认为哪种方法更好?


编辑:

从提议的解决方案中,似乎有两个重要问题我没有提到.

问:用户主要使用C/C++吗?

答:所有已知的开发都将采用C/C++或汇编语言.我正在设计这个库供我个人使用,主要用于裸机项目.将没有或最小的操作系统功能.在完整的操作系统中使用它的可能性很小,这需要考虑语言绑定.由于这是为了个人成长,因此在流行的嵌入式操作系统上学习库开发将是有利的.

问:用户是否需要/想要一个暴露的库?

:到目前为止,是的.由于它只是我,我想对测试后使用的每个处理器进行直接修改.这是测试套件有用的地方.所以一个暴露的图书馆会有所帮助.另外,特定功能的每个"最佳实现"可能具有失败的条件.此时,必须决定谁解决问题:用户或图书馆设计师.用户需要一个公开的库来解决失败的情况.我既是"用户"又是"图书馆设计师".两者都允许几乎更好.然后非实时应用程序可以让库解决所有稳定性问题,但是实时应用程序可以考虑算法速度/空间与算法稳定性.

Eug*_*eck 7

根据您图书馆的目标受众,我建议您选择两种方案:

  1. 如果您的库的使用者保证是Cish,请使用#define sqrt newton_sqrt以获得最佳可读性

  2. 如果您的库的某些消费者属于C类(想想绑定到Dephi,.NET,等等),请尽量避免消费者可见#defines.这是绑定的主要PITA,因为宏在二进制文件上不可见 - 嵌入式函数调用是最具绑定性的.


小智 7

另一种方法是将功能移动到针对每个不同体系结构优化的单独编译库中,然后在编译期间链接到该库.这将允许项目代码保持不变.


oua*_*uah 5

你能做的就是这个。在头文件 (.h) 中:

 int function(void);
Run Code Online (Sandbox Code Playgroud)

在源文件 (.c) 中:

static int function_implementation_a(void);
static int function_implementation_b(void);
static int function_implementation_c(void);

#if ARCH == ARCH_A
int function(void)
{
    return function_implementation_a(); 
}
#elif ARCH == ARCH_B
int function(void)
{
    return function_implementation_b();
}
#else
int function(void)
{
    return function_implementation_c();
}
#endif // ARCH
Run Code Online (Sandbox Code Playgroud)

调用一次的静态函数通常由实现内联。例如,gcc默认情况下 : -finline-functions-called-once是这种情况,即使在-O0. 未调用的静态函数通常也不包含在最终二进制文件中。

请注意,我没有将#ifand#else放在单个function主体中,因为当#if指令位于函数主体之外时,我发现代码更具可读性。

请注意,这种方式更适用于嵌入式代码,其中库通常以其源代码形式分发。