简体   繁体   English

为什么这个C宏会导致语法错误?

[英]Why is this C macro causing syntax error?

This is the first time I'm using macros in C and I'm trying to replace a large section of code that I'd normally place into a function with a macro. 这是我第一次在C中使用宏而我正在尝试替换我通常放入带宏的函数中的大部分代码。 This is a part of an interrupt which will be used quite often and therefore I need to optimize it as much as I can. 这是一个经常使用的中断的一部分,因此我需要尽可能地优化它。 After reading the documentation, I've seen that the compiler doesn't support function inlining and I want to avoid the function call overhead. 阅读完文档后,我发现编译器不支持函数内联,我想避免函数调用开销。

The code itself sends data to a serial-in parallel-out shift register and as far as I can see, there's no shorter way to write the piece of code I need. 代码本身将数据发送到串行输入并行移位寄存器,据我所知,编写我需要的代码片段没有更短的方法。

I'm using C18 compiler version 3.41 and MPLAB X IDE. 我正在使用C18编译器版本3.41和MPLAB X IDE。

So here's the code I'm using in function form: 所以这是我在函数形式中使用的代码:

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;
}

I've turned the function into this macro: 我已将该函数转换为此宏:

#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;\
\
                     }

So what am I doing wrong? 那么我做错了什么?

Update : I removed the comments and am now getting a syntax error in a different location. 更新 :我删除了评论,现在在不同的位置出现语法错误。

检查\\ tokens后没有空格,有些编译器为此发出编译错误。

Lines are spliced before comments are removed, so the \\ in \\//3 invisible zeroes does does not continue the line. 在删除注释之前拼接行,因此\\ in \\//3 invisible zeroes不会继续该行。

You need either to remove the comment or use a C-style comment ( /* 3 invisible zeroes */ ) and place the comment before the \\ that continues the line. 您需要删除注释或使用C风格的注释( /* 3 invisible zeroes */ )并将注释放在继续该行的\\ 之前

The problem is with the comments and the way the preprocessor deals with them. 问题在于评论和预处理器处理它们的方式。 Remove the comments and this should work fine. 删除评论,这应该工作正常。 Alternativly use /* Comment */ 另外使用/ *评论* /

Three suggestions: 三点建议:

First, make sure that there aren't any trailing spaces after each \\ . 首先,确保每个\\后没有任何尾随空格。

Second, drop the () from the macro name if it's not meant to take any arguments. 其次,如果它不打算接受任何参数,则从宏名称中删除 () edit struck per comments below. 编辑以下评论。

Finally, wrap the contents of the macro in a do {...} while(0) (with no trailing semicolon). 最后,将do {...} while(0)的内容包装在do {...} while(0) (没有尾随分号)。 This way, when you write first_one(); 这样,当你写first_one(); in your code, you won't have a spurious semicolon after the closing brace. 在你的代码中,在结束括号后你不会有一个虚假的分号。

In short, 简而言之,

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

edit Lundin points out that this is old-fashioned and unnecessary. 编辑伦丁指出,这是老式的,没有必要。 I always believed it was required to avoid a diagnostic if a macro expanded to a statement of the form {...}; 我一直认为,如果宏扩展为{...};形式的陈述,则需要避免诊断{...}; -- apparently I was wrong. - 显然我错了。 I still prefer it as a stylistic choice, though. 不过,我仍然喜欢它作为一种风格选择。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM