在函数内定义/使用宏 - 好 style/practice?

define / use a Macro inside a fcuntion - good style/practice?

伙计们,我有一个问题要问那里的 C/C++ 语法/编码风格专家:

情况:我正在研究 STM32 微控制器,在某些功能中我必须对位、set/clear 位和写入 / 进行大量位移、逻辑运算(和、或、异或)阅读这段代码真的很痛苦。

举个例子:假设我必须打开一个带有数字输出的设备,我有 5 个传感器要检查,每个传感器都有自己专用的数字输入。其中一些需要为 TRUE,其他需要为 FALSE

一个(伪)代码最终看起来像这样: 注意:这段代码显然nonsense/nothing真正起作用了,只是为了解释原理。

#define SENSOR1 0
#define SENSOR2 1
#define SENSOR3 2
#define SENSOR4 3
#define SENSOR5 4

void DeviceOn(void) {
   uint8_t DIOPort = ReadDIOPort();
   if((DIOPort & (1 << SENSOR1)) && (!(DIOPort & (1 << SENSOR2))) && (DIOPort & (1 << SENSOR3))) {
      turnOnDevice();
   } else {
      turnOffDevice();
   }
}

如您所见,if 条件变得非常丑陋,如果涉及的信号越多,它就会变得越来越不可读。

我的想法是在函数内部定义宏,仅供 / 在该函数内使用,以使代码更具可读性。这看起来像这样。

void DeviceOn(void) {
       #define __POWER_ISOK (DIOPort & (1 << SENSOR1))
       #define __SAFETY_ISOK (!(DIOPort & (1 << SENSOR2)))
       #define __LIGHT_ISON (DIOPort & (1 << SENSOR3))
       #define __COFFEEMUG_ISFULL (DIOPort & (1 << SENSOR4))
       uint8_t DIOPort = ReadDIOPort();
       if(__POWER_ISOK && __SAFETY_ISOK && __LIGHT_ISON && __COFFEEMUG_ISFULL) {
         turnOnDevice();
       } else {
         turnOffDevice();
       }
    }

恕我直言,if 条件作为第一个示例更具可读性。

问题是:这被认为是“良好的编码风格”还是绝对不行,其他开发人员将开始避开我并认为我是整个宇宙中最糟糕的编码员?

我希望在函数中定义宏,因为它们只在这个函数中使用,而且它使文档更容易:必须阅读这段代码的人只需向上滚动到函数的开头函数并且不必在 C 文件甚至头文件中搜索定义。数字输入状态变量中位的定义是全局定义的(在 C 文件的开头),因为它们也用于其他函数。

当然,我会全局定义在多个函数中使用的任何宏。当然我也可以全局定义所有的宏,但是我认为如果只在一个函数中使用的宏定义在那个函数中,这样会使代码更具可读性。

技术上我没有看到任何问题,因为预处理器应该替换构建过程中的宏,或者我错了吗?

替代解决方案:

#include <stdbool.h>

void DeviceOn(void)
{
    uint8_t DIOPort = ReadDIOPort();

    bool PowerIsOK       =    DIOPort & 1 << SENSOR1;
    bool SafetyIsOK      = ! (DIOPort & 1 << SENSOR2);
    bool LightIsOn       =    DIOPort & 1 << SENSOR3;
    bool CoffeeMugIsFull =    DIOPort & 1 << SENSOR4;

    if (PowerISOK && SafetyIsOK && LightIsOn && CoffeeMugIsFull)
        turnOnDevice();
    else
        turnOffDevice();
}

Marcos 没有作用域,它们的定义不会在函数结束时结束。

在函数内部定义宏,这样它们在函数之后仍然定义是一种不好的做法,因为程序员希望定义在作用域结束时结束。您可以取消定义函数末尾的宏。这是一个很好的做法当首先需要宏时这并不经常。

不必要地使用宏是一种不好的做法。在这种情况下,更好的做法是改用常量变量。变量有类型系统和范围,这两者都使编写正确的程序变得更容易。

P.S。包含两个连续下划线的名称保留给语言实现。不要自己定义它们。