Почему я получаю ошибки при компиляции этого кода и как их исправить?

Программа, которую я пытаюсь написать, включает макрос для округления действительного числа до ближайшего целого числа и функцию, которая использует этот макрос для округления массива действительных чисел.

Вот программа:

#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))

Изменения, которые я сделал, включают в себя:

  1. Делая это выражением. Это предполагает замену фигурных скобок скобками. Это так, что вы можете использовать макрос практически везде, где вы можете использовать функцию. Если бы я оставил фигурные скобки, это было бы сложным утверждением.

  2. Обернуть параметр 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 и, возможно, отставая ; также.

Другие вопросы по тегам