为什么这条线被混淆了?

时间:2015-03-17 10:59:58

标签: c

在此代码段中,

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)

6 个答案:

答案 0 :(得分:7)

RCC_OscInitStruct->OscillatorType是一个以整数值打包的位集合,每个位代表一个值(RCC_OSCILLATORTYPE_HSE,...)。这就是为什么它们具有2的幂。你展示的代码只是检查是否设置了与RCC_OSCILLATORTYPE_HSI相关的位。很可能还会设置其他值的位。

例如,如果OscillatorType的二进制表示为0...011,则设置第一个和第二个位,这意味着选择了RCC_OSCILLATORTYPE_HSERCC_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_HSI0之间的按位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

也许这就是该代码的程序员所期望的,但他们并没有完全把代码带到那里。