2012-05-05 4 views
2

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

Сам код отправляет данные в последовательный регистр с параллельным выводом, и, насколько я могу судить, более короткий способ написать часть кода, в которой я нуждаюсь.

Я использую компилятор C18 версии 3.41 и MPLAB X IDE.

Так вот код, я использую в виде функции:

void first_one(void) 
{ 
    //3 invisible zeroes 
      LATBbits.LATB1=0; //data set to zero 

      LATBbits.LATB0=1;//first clock 
      LATBbits.LATB0=0; 

      LATBbits.LATB0=1;//second clock 
      LATBbits.LATB0=0; 

      LATBbits.LATB0=1;//third clock 
      LATBbits.LATB0=0; 
      //end of invisible zeroes 

      //two visible zeroes  
      LATBbits.LATB0=1;//first clock 
      LATBbits.LATB0=0; 

      LATBbits.LATB0=1;//second clock 
      LATBbits.LATB0=0; 
      //end of two visible zeroes 

      LATBbits.LATB1=1;//Data is now one 

      LATBbits.LATB0=1; 
      LATBbits.LATB0=0; 
      //one 

      LATBbits.LATB1=0;//Data is now zero 

      LATBbits.LATB0=1;//first clock 
      LATBbits.LATB0=0; 

      LATBbits.LATB0=1;//second clock 
      LATBbits.LATB0=0; 

      //after this, everything should be in place 
      LATBbits.LATB0=1; 
      LATBbits.LATB0=0; 
} 

Я перевернул функцию в этот макрос:

#define first_one() { \ 
\ 
      LATBbits.LATB1=0;\    
           \ 
      LATBbits.LATB0=1;\ 
      LATBbits.LATB0=0;\ 
           \ 
      LATBbits.LATB0=1;\ 
      LATBbits.LATB0=0;\ 
          \ 
      LATBbits.LATB0=1;\ 
      LATBbits.LATB0=0;\ 
      \         
      LATBbits.LATB0=1;\ 
      LATBbits.LATB0=0;\ 
\ 
      LATBbits.LATB0=1;\ 
      LATBbits.LATB0=0;\ 
      \ 
      LATBbits.LATB1=1;\ 
\ 
      LATBbits.LATB0=1;\ 
      LATBbits.LATB0=0;\  
\ 
      LATBbits.LATB1=0;\ 
      ^^^ The syntax error is here! 
\ 
      LATBbits.LATB0=1;\ 
      LATBbits.LATB0=0;\ 
\ 
      LATBbits.LATB0=1;\ 
      LATBbits.LATB0=0;\ 
\ 
      LATBbits.LATB0=1;\ 
      LATBbits.LATB0=0;\ 
\ 
        } 

Так что я делаю неправильно?

Обновление: Я удалил комментарии и теперь получаю синтаксическую ошибку в другом месте.

+0

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

+0

@Paul R Как я уже сказал в вопросе, компилятор не поддерживает функцию inlining. – AndrejaKo

+1

... но, как сказал Пол, действительно ли здесь важна накладная функция вызова - это не одна функция линии в конце концов. Похоже на [преждевременную оптимизацию] (http://c2.com/cgi/wiki?PrematureOptimization) для меня. – Clifford

ответ

8

Проверьте, нет ли пробелов после токенов \, некоторые компиляторы выдают ошибку компиляции для этого.

+0

Я проверил пробелы, подтвердил, что их нет, и ошибка все еще там. – AndrejaKo

+0

На самом деле выясняется, что это была проблема. После повторного запуска IDE несколько раз и, увидев, что программа скомпилирована в порядке, я попытался добавить пробел после '\' и получил синтаксическую ошибку, как и вначале. – AndrejaKo

+2

Вот совет: в вашем редакторе выберите/выделите весь текст макроса; любое конечное пространство будет отображаться как цветной блок в конце строки нарушения. Вы даже можете сделать это с текстом в заданном вопросе и посмотреть, где проблема. – Clifford

3

Линии сплайсируются перед удалением комментариев, поэтому \ в \//3 invisible zeroes не продолжает линию.

Вам нужно либо удалить комментарий или использовать C-стиль комментария (/* 3 invisible zeroes */) и поместить комментарий перед тем в \, который продолжает линию.

+0

Похоже, главная проблема - не комментарии. Я удалил их и все еще получаю синтаксическую ошибку. – AndrejaKo

+0

Какова синтаксическая ошибка? Посмотрите на предварительно обработанный источник и выясните, что не так (скомпилируйте с '-E' на gcc и Visual C++). –

+0

Синтаксическая ошибка: «Ошибка: синтаксическая ошибка», поэтому это не очень полезно. Visual Studio и GCC не поддерживают платформу, на которой я пишу код прямо сейчас. – AndrejaKo

1

Проблема связана с комментариями и тем, как препроцессор справляется с ними. Удалите комментарии, и это должно работать нормально. Альтернативное использование/* Комментарий */

1

Три предложения:

Во-первых, убедитесь, что нет никаких завершающих пробелов после каждого \.

Во-вторых, оставьте () от имени макроса, если оно не предназначено для принятия каких-либо аргументов. Редактировать ударил в комментариях ниже.

Наконец, оберните содержимое макроса в do {...} while(0) (без конечной точки с запятой). Таким образом, когда вы пишете first_one(); в своем коде, у вас не будет ложной точки с запятой после закрытия.

Короче говоря,

#define do_first   \ 
    do {     \ 
    LATBbits.LATB0 = 1; \ 
    ...     \ 
    } while(0) 

редактировать Лундин указывает на то, что это старомодно и ненужным. Я всегда считал, что нужно избегать диагностики, если макрос развернут до утверждения формы {...}; - по-видимому, я был неправ. Тем не менее, я все же предпочитаю это как стилистический выбор.

+4

Я никогда не пропускаю() из макросов, которые должны действовать как функции, даже если они не принимают аргументов. Это делает код более понятным для чтения (это функция вроде оператора), а не просто голый символ. –

+0

Я согласен, всегда используйте() для макросов, чтобы они выглядели как C, и чтобы они были совместимы с встроенными функциями, вы должны получить стандартный компилятор C в будущем. Кроме того, советы по-старому старомодны. Все современные стандарты C-кодирования обеспечивают {} после каждого утверждения, чтобы уменьшить количество ошибок. Поэтому делать это пока не нужно, если у вас есть какая-то кодирующая дисциплина. – Lundin

+0

@ Lundin: Я буду проклят. Я мог бы присягнуть * '{...};' вызвал бы изжогу, но gcc проглатывает ее просто отлично, даже с -pendatic. И я приму аргументы в пользу сохранения '()'. Я стараюсь избегать использования макросов для чего-либо, кроме символических констант - слишком много изжоги. –

Смежные вопросы