Почему я получаю ошибки при компиляции этого кода и как их исправить?
Программа, которую я пытаюсь написать, включает макрос для округления действительного числа до ближайшего целого числа и функцию, которая использует этот макрос для округления массива действительных чисел.
Вот программа:
#include <stdio.h>
#define SIZE 256
#define round(N) { return (N >=0)? (int)(N+0.5) : (int)(N-0.5) ; }
void round_array(int a[])
{
int i;
for(i=0; i <SIZE; i++)
{
a[i] = round(a[i]);
}
}
int main()
{
return 0;
}
При компиляции я получаю следующие ошибки:
round.c: In function ���round_array���:
round.c:4:18: error: expected expression before ���{��� token
#define round(N) { return (N >=0)? (int)(N+0.5) : (int)(N-0.5) ; }
^
round.c:11:15: note: in expansion of macro ���round���
a[i] = round(a[i]);
^
round.c: At top level:
Почему я получаю эти ошибки и как их исправить?
5 ответов
Потому что после предварительной обработки ваш код будет выглядеть примерно так:
a[i] = { return (a[i] >=0)? (int)(a[i]+0.5) : (int)(a[i]-0.5) ; }
Если вам нравится придерживаться макроса, объявите его как:
#define round(N) ((N) >=0)? (int)((N)+0.5) : (int)((N)-0.5)
Но это все еще не совсем правильно из-за смешивания int/float. Это, однако, уже другая тема.
Если вы настаиваете на том, чтобы написать это самостоятельно, вам следует заменить макрос icky на более безопасную и чистую функцию:
inline int int_round (double d)
{
return (int) ( d >= 0 ? d+0.5 : d-0.5 );
}
Это должно дать тот же машинный код.
Как было сказано в комментарии, макросы не являются функциями. Это механизм замены токенов. Таким образом, вы не вернетесь от них, как если бы вы работали.
#define round(N) (((N) >=0)? (int)((N)+0.5) : (int)((N)-0.5))
Изменения, которые я сделал, включают в себя:
Делая это выражением. Это предполагает замену фигурных скобок скобками. Это так, что вы можете использовать макрос практически везде, где вы можете использовать функцию. Если бы я оставил фигурные скобки, это было бы сложным утверждением.
Обернуть параметр N в скобки также, чтобы убедиться, что приоритет оператора не возвращается и не кусает нас.
Макро-замена - это то, на что это похоже, она заменяет макрос на тело макроса, буквально.
Итак, когда у вас есть
a[i] = round(a[i]);
Будет заменено
a[i] = { return (a[i] >=0)? (int)(a[i]+0.5) : (int)(a[i]-0.5) ; };
Это неверный синтаксис. Правая часть присваивания должна быть выражением, а не утверждением.
Простое решение состоит в том, чтобы превратить round
от макроса к реальной функции. Еще более простое решение - понять, что int
ценности (a[i]
является int
) не имеет дробей, поэтому округлять нечего.
Если вы хотите использовать значения с плавающей точкой, правильное решение заключается в использовании стандартного round
функция, а не придумывать свои.
Вам не нужно return
Ключевое слово, это не функция. Избавиться от этого.
квотирование C11
глава §6.8.6.4
return
инструкция завершает выполнение текущей функции и возвращает управление ее вызывающей стороне . [...]
что не является целью вашего определения MACRO. Включение return
ключевое слово является нежелательным и неверный синтаксис там.
То, что вы, вероятно, хотите, это синтаксис
(N >=0)? (int)(N+0.5) : (int)(N-0.5)
или что-то лучше
( (N) >=0)? (int)((N)+0.5) : (int)((N)-0.5)
без return
и, возможно, отставая ;
также.