Вы можете объявить макрос в любом месте кода, но если у вас нет особых причин ограничивать его использование функцией, он обычно появляется в начале файла .c
или в файле .h
.
Макросы работают по подстановке. Поэтому, если у вас есть что-то похожее на следующее:
#define MIN(A, B) {(A) < (B) ? (A) : (B);}
int main(void)
{
int min = MIN(MIN(a, b), c);
}
Это будет предварительно обработано в:
int min = {({(a) < (b) ? (a) : (b);}) < (c) ? ({(a) < (b) ? (a) : (b);}) : (c);};
Вы можете увидеть это сами, если используете GCC, с помощью командыgcc -E source.c
. Это явно не то, что вы хотели, и это даст вам ошибку компиляции.
Мы никогда не используем ;
в конце макросов, и не помещаем их в блоки. Чтобы избежать неожиданной связи оператора со сложными выражениями, мы защищаем параметры макроса и весь макрос в скобках.
Ваш макрос MIN
должен выглядеть примерно так:
#define MIN(A, B) ((A) < (B) ? (A) : (B))
Наконец, естьдве вещи, происходящие с вашим макросом MIDRANGE
. Во-первых, он должен принимать аргументы, как вы сделали с MIN
. В идеале это должно быть три аргумента;в конце концов, вся причина сделать это макросом, чтобы пользователю макроса не приходилось все вычислять. Во-вторых, если вы хотите, чтобы результат был числом с плавающей запятой, вы должны разделить его на 2,0, а не на 2.
Вот мое первое предложение:
#define MIDRANGE(A, B, C) ((MIN(MIN(A, B), C) + MAX(MAX(A, B), C)) / 2.0)
Однако почему это так? макрос? Сделайте это функцией. Это более читабельно, и легче поддерживать. Итак, вот мое второе предложение:
double midrange(int a, int b, int c)
{
int min = MIN(MIN(a, b), c);
int max = MAX(MAX(a, b), c);
return (min + max) / 2.0;
}