我已完成此代码,以便在运行时由预处理器对其进行评估。
#define setPinToPortBit(pin)\
if (pin < 19) PORTD ## pin;\
else if(pin>14) PORTB ## (pin-14)\
else PORTC ## (pin - 8)
#define STATION1 setPinToPortBit(15)
有没有办法知道这个代码示例何时会被评估?
是否在预处理时对其进行评估,以便在编译之前,digitalWrite(STATION1, 1)
或某些包含digitalWrite(PORTB1, 1)
等ifs和elses的扩展内容会产生代码digitalWrite(if(15<19)....
?
答案 0 :(得分:1)
假设你有一行
digitalWrite(STATION1, 1)
预处理器将把它变成(假设我仍然可以做数学):
digitalWrite(if (15 < 19) PORTD15; else if(15>14) PORTB1 else PORTC7)
现在,据我所知,这不会编译,因为if
是void
类型的语句,这意味着它不会产生值。为了使事情顺利,你需要做的就是
#define setPinToPortBit(pin) \
pin < 19 \
? PORTD ## pin \
: pin > 14 \
? PORTB ## (pin-14) \
: PORTC ## (pin - 8)
现在,预处理器会将该行转换为
digitalWrite(15<19 ? PORTD15 : 15>14 ? PORTB1 : PORTC7);
这是正确的C,如果PORTD15
,PORTB1
和PORTC7
是具有相同静态类型的有效常量。
现在,C编译器将编译它。根据标准,编译器有权编译此代码,就好像它是
一样digitalWrite(PORTD15);
但这不是强制性的:编译器可以根据它想要的任何东西来选择。
我经常看到的是,如果启用优化,所有体面的现代编译器都可以并且将预先评估这些常量条件。 如果未启用优化或者您正在调试模式下进行编译,那么我认为编译器将保持语句不变,而无需预先评估条件。因为您可能想要介入它们并通过调试器更改自然执行,然后您可能希望编译并使用该代码,即使它通常不会被执行。
当然,您可以通过反汇编可执行文件并进行分析来获得更准确的信息。
答案 1 :(得分:1)
在正确运行编译器之前,宏由预处理器进行扩展。
代码的扩展版本如下所示,
digitalWrite( if (15 < 19) PORTD15; else if(15>14) PORTB (15-14) else PORTC (15 - 8), 1)
您可以使用gcc -E file.c
查看预处理的输出。它将在预处理阶段后停止。输出采用预处理源代码的形式,发送到标准输出。不需要预处理的输入文件将被忽略。
使用条件有三个一般原因。
不需要系统特定逻辑或复杂调试挂钩的简单程序通常不需要使用预处理条件。
条件指令是:
#ifdef - If this macro is defined
#ifndef - If this macro is not defined
#if - Test if a compile time condition is true
#else - The alternative for #if
#elif - #else an #if in one statement
#endif - End preprocessor conditional
的示例:
#ifdef DEBUG
/* Your debugging statements here */
#endif
#if((NUM%2)==0)
printf("\nNumber is Even");
#else
printf("\nNumber is Odd");
#endif
答案 2 :(得分:0)
这取决于评估的含义。
预处理器通过代码扩展(换句话说,复制粘贴)定义。
常量和常量表达式的评估将在编译时完成。 if子句,如果转到if(true)或if(false)将在编译时进行评估,编译器可能会决定删除无法访问的代码。
如果你想要预处理器评估的if子句有#if,#elif或#else。
答案 3 :(得分:0)
如果您询问预处理器是否会对变量进行检查,然后为您应用正确的定义,则答案为 NO 。顺序是预处理器指令将被评估&amp;在编译器接受作业之前由预处理器替换,因此预处理器不知道正常变量的值是什么,并且无法为您进行检查。
预处理器将执行的操作是查找使用指令的位置,并将其替换为您的代码段。