我有一个简单的函数,我在操作代码中为
C
编译,在测试中为 C++
编译。由于我将在代码中广泛使用此函数,因此我想在实用程序文件中声明它并使其尽可能高效。
让我们考虑一个计算两个
uint64_t
值之间的绝对差的示例函数。
这里有三个选项:
选项1:
constexpr uint64_t diff(uint64_t a, uint64_t b)
{
return a > b ? a - b : b - a;
}
在 C++ 中,该函数将在编译时求值并隐式内联。
在C中,
constexpr
将被忽略,仅表示函数的返回值为constexpr
。
选项2:
constexpr inline uint64_t diff(uint64_t a, uint64_t b)
{
return a > b ? a - b : b - a;
}
在 C++ 中,该函数将在编译时求值并隐式内联。
inline
关键字是多余的。
在C中,
constexpr
会被忽略,仅暗示函数的返回值为constexpr
,并且有提示编译器切换函数与函数体。
选项3:
#define DIFF(a, b) ((a) > (b) ? ((a) - (b)) : ((b) - (a)))
在 C++ 中,它可以工作,但使用
constexpr
函数可以增加类型安全性。
在 C 中,它可以工作,并且可能是最有效的方法,就像在内联函数中一样,编译器可能会忽略内联。
哪个选择更好,为什么?还有第四种选择吗?
请记住,我需要为
c
和c++
选择最佳选择。
理想的选择是你还没有提到的:
constexpr static inline uint64_t diff(uint64_t a, uint64_t b)
{
return a > b ? a - b : b - a;
}
C 语言需要
static inline
的原因是 inline
在 C 中的工作方式不同。它仅仅让您提供内联定义,但如果该函数实际上并未内联(例如在调试版本中),您会得到一个链接器错误而不在某个地方声明它extern inline
。
static inline
避免了这个问题,并允许您通过内部链接定义标头中的所有内容。
虽然很脏,但是有用。
在 C++ 中,
static inline
是合法的,尽管有点多余。
constexpr
已经使函数成为内联函数,我们不需要使用 static
来解决此问题,因此您也可以编写:
#ifdef __cplusplus
#define C_STATIC_INLINE
#else
#define C_STATIC_INLINE static inline
#endif
#define
constexpr C_STATIC_INLINE uint64_t diff(uint64_t a, uint64_t b)
{
return a > b ? a - b : b - a;
}