Я недавно запустил маленький персональный проект (значение RGB к BGR оценивают программу преобразования) в C, и я понял, что функция, которая преобразовывает от RGB до BGR, может не только выполнить преобразование, но также и инверсию. Очевидно, это означает, что мне действительно не нужны две функции rgb2bgr
и bgr2rgb
. Однако имеет значение, использую ли я указатель функции вместо макроса? Например:
int rgb2bgr (const int rgb);
/*
* Should I do this because it allows the compiler to issue
* appropriate error messages using the proper function name,
* not to mention possible debugging benefits?
*/
int (*bgr2rgb) (const int bgr) = rgb2bgr;
/*
* Or should I do this since it is merely a convenience
* and they're really the same function anyway?
*/
#define bgr2rgb(bgr) (rgb2bgr (bgr))
Я не обязательно смотрю для разнообразия в эффективности выполнения, поскольку это - больше субъективного вопроса из любопытства. Я хорошо знаю о том, что безопасность типов ни не потеряна, ни получила использование любого метода. Указатель функции просто был бы удобством или является там более практическими преимуществами, которые будут получены, которые я не знаю?
Другой вариант - просто вызвать первую функцию из второй и позволить компилятору позаботиться об ее оптимизации (путем встраивания или генерации хвостового вызова).
Я бы использовал макрос. Он более распространен и более идиоматичен, и у него меньше проблем с пересечением единиц трансляции (т.е. вам не нужно беспокоиться о том, чтобы объявить макрос статическим).
Кроме того, используя указатель функции, вы предотвращаете инлайнинг в большинстве компиляторов.
Наконец, используя указатель функции, клиенты могут сделать следующее:
int evil(const int bgr) { /* Do something evil */ }
bgr2rgb = evil
Конечно, они, вероятно, не хотят этого, но возможно, что в дальнейшем появится переменная с именем, похожим на bgr2rgb
, где потребуется всего одна опечатка.
Макрос безопаснее, хотя я бы определил его так - здесь не нужен макрос, похожий на функцию:
#define bgr2rgb rgb2bgr