#定义带逗号的表达式
#define expression with comma
我遇到了一个包含以下表达式的 #define
语句。我不明白整个语句或逗号在括号内分隔两个表达式的作用。好像是一个函数,我猜不是。
#define LCD_SELECT_CS1 (PORTD |= (1<<3), PORTD &= ~(1<<2))
C 中的逗号只是表达式和构造表达式的顺序运算符。这意味着:
e1, e2, ..., en
是一个表达式,其值为 en 的表达式,计算 e1
,然后 e2
,... 然后 en
我想这里有两个问题:
- 它有什么作用/它是如何工作的?
- 为什么要这样写?
它的工作原理是使用 逗号运算符,这可能是 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)
包含 OR
的 PORTD
和 Bit3
(1 左移 3 次)。如果该位尚未设置并且不更改端口中的任何其他位,则应设置该位。
- 接下来,宏使用
PORTD &= ~(1<<2)
清除 PORTD
的 Bit2
,其中 ~(1<<2)
作为位掩码始终导致 Bit2
到 0
因为该位将在掩码中设置为 0
,而所有其他位都设置为 1
。宏 returns Bit2
的新值(始终为 0)。
更新:根据 Antoine Mathys 的出色观察更正第二点。
我遇到了一个包含以下表达式的 #define
语句。我不明白整个语句或逗号在括号内分隔两个表达式的作用。好像是一个函数,我猜不是。
#define LCD_SELECT_CS1 (PORTD |= (1<<3), PORTD &= ~(1<<2))
C 中的逗号只是表达式和构造表达式的顺序运算符。这意味着:
e1, e2, ..., en
是一个表达式,其值为 en 的表达式,计算 e1
,然后 e2
,... 然后 en
我想这里有两个问题:
- 它有什么作用/它是如何工作的?
- 为什么要这样写?
它的工作原理是使用 逗号运算符,这可能是 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)
包含OR
的PORTD
和Bit3
(1 左移 3 次)。如果该位尚未设置并且不更改端口中的任何其他位,则应设置该位。- 接下来,宏使用
PORTD &= ~(1<<2)
清除PORTD
的Bit2
,其中~(1<<2)
作为位掩码始终导致Bit2
到0
因为该位将在掩码中设置为0
,而所有其他位都设置为1
。宏 returnsBit2
的新值(始终为 0)。
更新:根据 Antoine Mathys 的出色观察更正第二点。