它是否在运行前由预处理器评估?

Is it evaluated by preprocessor before runtime?

我完成这段代码是为了让预处理器在运行时对其进行评估。

#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 和 else 的扩展内容,如 digitalWrite(if(15<19)....

这取决于你所说的评价。

预处理器通过代码扩展(换句话说,复制粘贴)定义。

常量和常量表达式的计算将在编译时完成。 if 子句,如果它们转向 if (true) 或 if (false),将在编译时进行评估,编译器可能会决定删除无法访问的代码。

如果你想要预处理器评估的 if 子句,可以使用 #if 、 #elif 或 #else 。

假设你有行

digitalWrite(STATION1, 1)

预处理器会将它变成(假设我仍然可以做数学):

digitalWrite(if (15 < 19) PORTD15; else if(15>14) PORTB1 else PORTC7)

现在,据我所知,这无法编译,因为 ifvoid 类型的语句,这意味着它不会产生值。为了把事情弄清楚,你需要做的就是

#define setPinToPortBit(pin) \
    pin < 19 \
        ? PORTD ## pin \
        : pin > 14 \
            ? PORTB ## (pin-14) \
            : PORTC ## (pin - 8)

现在,预处理器会将行变成

digitalWrite(15<19 ? PORTD15 : 15>14 ? PORTB1 : PORTC7);

这是正确的 C,如果 PORTD15PORTB1PORTC7 是具有相同静态类型的有效常量。

现在,C 编译器将编译它。按照标准,编译器被授权编译这段代码,就好像它是

digitalWrite(PORTD15);

但这不是强制性的:编译器可以根据需要进行选择。

我通常看到的是,如果启用优化,所有体面的现代编译器都可以并且将会预先评估这些常量条件。 如果未启用优化或您在调试模式下编译,那么我认为编译器将保持语句原样,而无需预先评估条件。因为您可能想要进入它们并通过调试器更改自然执行,然后您可能希望该代码被编译并可用,即使它通常永远不会被执行。

当然,您可以通过反汇编您的可执行文件并对其进行分析来获得更准确的信息。

宏在运行正确编译器之前由预处理器扩展。

您的代码的扩展版本如下所示,

digitalWrite( if (15 < 19) PORTD15; else if(15>14) PORTB (15-14) else PORTC (15 - 8), 1)

您可以使用 gcc -E file.c 查看预处理后的输出。它将在预处理阶段后停止。输出以预处理源代码的形式发送到标准输出。不需要预处理的输入文件将被忽略。

使用条件句的三个一般原因。

  1. 程序可能需要使用不同的代码,具体取决于机器或 操作系统是要运行上的。在某些情况下,一个代码 操作系统在另一个操作系统上可能是错误的;为了 例如,它可能引用不存在的数据类型或常量 在另一个系统上。当发生这种情况时,仅仅避免是不够的 执行无效代码。它的存在将导致 编译器拒绝该程序。通过预处理条件, 有问题的代码可以从程序中有效地删除 无效。
  2. 您可能希望能够将同一个源文件编译成两个 不同的程序。一个版本可能会使频繁耗时 对其中间数据进行一致性检查,或打印值 那些用于调试的数据,而另一个则不是。
  3. 条件始终为假的条件是一种排除方法 程序中的代码,但保留它作为将来的一种评论 参考。

不需要系统特定逻辑或复杂调试挂钩的简单程序通常不需要使用预处理条件。

条件指令是:

#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

如果您询问预处理器是否会进行变量检查,然后为您应用正确的定义,答案是。顺序是预处理器指令将在编译器开始工作之前被预处理器评估和替换,因此预处理器不知道普通变量的值是什么,也无法为您进行检查。

不过,预处理器要做的是找到使用指令的位置,并将其替换为您的代码片段。