在此代码段中,
if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI)
{
/* statements */
}
成员OscillatorType
可以包含以下定义的任何值或其组合。
#define RCC_OSCILLATORTYPE_NONE ((uint32_t)0x00000000)
#define RCC_OSCILLATORTYPE_HSE ((uint32_t)0x00000001)
#define RCC_OSCILLATORTYPE_HSI ((uint32_t)0x00000002)
#define RCC_OSCILLATORTYPE_LSE ((uint32_t)0x00000004)
#define RCC_OSCILLATORTYPE_LSI ((uint32_t)0x00000008)
为什么if
这样写?为什么不这么简单?
if(RCC_OscInitStruct->OscillatorType == RCC_OSCILLATORTYPE_HSI)
答案 0 :(得分:7)
RCC_OscInitStruct->OscillatorType
是一个以整数值打包的位集合,每个位代表一个值(RCC_OSCILLATORTYPE_HSE
,...)。这就是为什么它们具有2的幂。你展示的代码只是检查是否设置了与RCC_OSCILLATORTYPE_HSI
相关的位。很可能还会设置其他值的位。
例如,如果OscillatorType
的二进制表示为0...011
,则设置第一个和第二个位,这意味着选择了RCC_OSCILLATORTYPE_HSE
和RCC_OSCILLATORTYPE_HSI
值。
答案 1 :(得分:3)
因为它可能同时具有中的任何值。 &
(按位AND)运算符用于仅提取值RCC_OSCILLATOR_TYPE_HSI
。
例如,您的输入可能如下所示:
010011
虽然RCC_OSCILLATOR_TYPE_HSI
看起来像这样:
000010
具有这两个值的AND运算符将返回000010
,完全等于RCC_OSCILLATOR_TYPE_HSI
。
但是,如果您的输入如下所示:
110101
此RCC_OSCILLATOR_TYPE_HSI
与0
之间的按位AND运算符将返回false
,条件将为{{1}}。
答案 2 :(得分:3)
这是一种非常常见的C语言,并且不会以任何方式混淆。这是两个非常不同的测试。
if ((RCC_OscInitStruct->OscillatorType & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI)
表示“如果RCC_OSCILLATOR_HSI
位为1”。它不关心任何其他位是0还是1,而
if (RCC_OscInitStruct->OscillatorType == RCC_OSCILLATORTYPE_HSI)
表示“如果RCC_OSCILLATOR_HSI
位为1 AND ,则所有其他位均为0”。
答案 3 :(得分:2)
if
条件仅对RCC_OscInitStruct->OscillatorType
的倒数第二位感兴趣。所以RCC_OSCILLATORTYPE_HSI
用作掩码,然后与自身进行比较。
如果你看到所有的常数,那么第一个是全零,而其他常数在连续的位置都有它的位置。
现在,使用任何这些常量执行&
可以告诉您是否在所述参数中设置了相应的位。
如果你想设置所有可能的值,你会这样做:
RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_LSI;
为什么要使用==
进行比较?
这不是必需的,会使代码混乱。我认为程序员在测试RCC_OSCILLATORTYPE_NONE
时希望带来一致性。
程序员无法测试RCC_OscInitStruct->OscillatorType & RCC_OSCILLATORTYPE_NONE
,因为它会评估为zero
。你要么被迫否定这个检查的条件。
答案 4 :(得分:1)
一个例子:
#include <stdio.h>
#include <stdint.h>
#define RCC_OSCILLATORTYPE_NONE ((uint32_t)0x00000000)
#define RCC_OSCILLATORTYPE_HSE ((uint32_t)0x00000001)
#define RCC_OSCILLATORTYPE_HSI ((uint32_t)0x00000002)
#define RCC_OSCILLATORTYPE_LSE ((uint32_t)0x00000004)
#define RCC_OSCILLATORTYPE_LSI ((uint32_t)0x00000008)
int main(void)
{
/* set HSI and HSE */
uint32_t flags = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI;
if (flags == RCC_OSCILLATORTYPE_HSI) {
puts("flags = HSI");
}
if ((flags & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI) {
puts("HSI is set in flags");
}
return 0;
}
输出:
HSI is set in flags
答案 5 :(得分:0)
首先,==
与&
不相同。因为==
查看整个32位寄存器,包括你不感兴趣的任何废话。虽然&
只是查看相关部分。
&
是用于按位AND的简单二进制算术。在我看来,你需要在注册你的第一个程序员课程之前理解二进制数,但也许这只是我。
无论如何,鉴于你实际上理解了按位AND的作用,如果你有像
那样的代码会更有意义#define RCC_OSCILLATORTYPE ((uint32_t)0x0000000F) // mask
#define RCC_OSCILLATORTYPE_NONE ((uint32_t)0x00000000)
#define RCC_OSCILLATORTYPE_HSE ((uint32_t)0x00000001)
#define RCC_OSCILLATORTYPE_HSI ((uint32_t)0x00000002)
#define RCC_OSCILLATORTYPE_LSE ((uint32_t)0x00000004)
#define RCC_OSCILLATORTYPE_LSI ((uint32_t)0x00000008)
...
(RCC_OscInitStruct->OscillatorType & RCC_OSCILLATORTYPE) == RCC_OSCILLATORTYPE_HSI
也许这就是该代码的程序员所期望的,但他们并没有完全把代码带到那里。