I have a utility struct defined in a library API, that has four fields, all numeric counters.
typedef struct {
size_t bytes;
int codepoints;
int graphemes;
int columns;
} TickitStringPos;
I want to provide some utilities to easily work on these structures. I could implement these as (static inline) functions, such as
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);
Or I could implement these as macros, such as
#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);
What should I consider weighing up these two approaches? Each are likely to be as powerful and flexible, but is one approach specifically preferable for some reason?
Prefer functions over macro for the simple reason that they provide you type safety unlike macros.
Also, with functions you don't have to take care of any side effects unlike macros.
As for the function being inline
it is just an indication to the compiler of your wish it is not binding on the compiler to make the function inline
, however any modern compiler will easily do the needful.