#定义带逗号的表达式

#define expression with comma

我遇到了一个包含以下表达式的 #define 语句。我不明白整个语句或逗号在括号内分隔两个表达式的作用。好像是一个函数,我猜不是。

#define LCD_SELECT_CS1 (PORTD |= (1<<3), PORTD &= ~(1<<2))

C 中的逗号只是表达式和​​构造表达式的顺序运算符。这意味着:

e1, e2, ..., en

是一个表达式,其值为 en 的表达式,计算 e1,然后 e2,... 然后 en

我想这里有两个问题:

  1. 它有什么作用/它是如何工作的?
  2. 为什么要这样写?

它的工作原理是使用 逗号运算符,这可能是 C 中最少使用的运算符。它基本上意味着,"first do the first thing, then do the second thing." 它与函数调用中分隔参数的逗号或分隔声明符的逗号 不同(即使看起来相同)像 int i, j; 这样的多重声明。另见 How does the Comma Operator work?

然后是 "style" 为什么这样写的问题,或者这样写是否是个好主意。

C 中的宏通过文本替换工作。它们不必看起来像任何东西,也不必有意义,一般来说,理解它们的唯一方法是查看展开它们后得到的结果。在这里,每当你写LCD_SELECT_CS1,你得到的是

(PORTD |= (1<<3), PORTD &= ~(1<<2))

如果您能理解 (PORTD |= (1<<3), PORTD &= ~(1<<2)) 的作用,您就大功告成了。

通常,为了避免混淆,宏应该扩展为单个对象或表达式,或者如果它扩展为一系列事物,则它应该是带有参数列表的 "function-like macro",更像是一个函数。由于这个 LCD_SELECT_CS1 宏与这些模式中的任何一个都不匹配,我们发现它 令人困惑的,因此风格很差。

事情是这样的:

  • PORTD |= (1<<3) 包含 ORPORTDBit3(1 左移 3 次)。如果该位尚未设置并且不更改端口中的任何其他位,则应设置该位。
  • 接下来,宏使用 PORTD &= ~(1<<2) 清除 PORTDBit2,其中 ~(1<<2) 作为位掩码始终导致 Bit20 因为该位将在掩码中设置为 0,而所有其他位都设置为 1。宏 returns Bit2 的新值(始终为 0)。

更新:根据 Antoine Mathys 的出色观察更正第二点。