API结构实用程序 - 函数或宏?

时间:2012-04-19 16:34:26

标签: c macros inline-functions

我有一个在库API中定义的实用程序结构,它有四个字段,所有数字计数器。

typedef struct {
  size_t bytes;
  int    codepoints;
  int    graphemes;
  int    columns;
} TickitStringPos;

我想提供一些实用程序来轻松处理这些结构。我可以将它们实现为(静态内联)函数,例如

static inline void tickit_stringpos_zero(TickitStringPos *pos) {
  pos->bytes = pos->codepoints = pos->graphemes = pos->columns = 0;
}

static inline void tickit_stringpos_limit_columns(TickitStringPos *pos, int columns) {
  pos->bytes = pos->codepoints = pos->graphemes = -1;
  pos->columns = columns;
}

TickitStringPos here, limit;
tickit_stringpos_zero(&here);
tickit_stringpos_limit_columns(&limit, 20);

或者我可以将它们实现为宏,例如

#define TICKIT_STRINGPOS_ZERO(pos) do { \
  (pos).bytes = (pos).codepoints = (pos).graphemes = (pos).columns = 0; \
} while(0);

#define TICKIT_STRINGPOS_LIMIT_COLUMNS(pos,_columns) do { \
  (pos).bytes = (pos).codepoints = (pos).graphemes = -1; \
  (pos).columns = _columns; \
} while(0);

TickitStringPos here, limit;
TICKIT_STRINGPOS_ZERO(here);
TICKIT_STRINGPOS_LIMIT_COLUMNS(limit, 20);

我应该考虑如何权衡这两种方法?每一种都可能具有强大和灵活性,但出于某种原因,这种方法是特别优选的吗?

3 个答案:

答案 0 :(得分:2)

首选宏功能,原因很简单,它们为您提供类型安全,而不像宏 此外,使用功能,您不必像宏那样处理任何副作用。

对于函数为inline,它只是向编译器表明你希望它没有绑定到编译器来创建函数inline,但是任何现代编译器都很容易做到需要

答案 1 :(得分:0)

正如Als所说,我认为在存在这种可能性时应该使用函数,出于维护原因。因为它们是内联的,所以没有性能损失。保留常量的宏,或者可能(非常)小的计算。

(注意: inline 关键字使一个函数被替换到位,节省了上下文切换开销,但引入了空间问题。除非你想为速度提供空间,你也可以使用常规函数)

答案 2 :(得分:0)

宏在编译器范围之前(之前)进行评估,这是针对这些宏的主要参数(大多数时候它们是不必要的第二个)。你可以通过Bjarne Stroustrup自己here找到一个很好的解释。