15

如果我有一些枚举,比如

typedef enum {
    AN_TRISTATE_0,
    AN_TRISTATE_1,
    AN_NOTHING,
    AN_MOTOR_1,
    AN_MOTOR_2,
    AN_MOTOR_3,
    AN_SENSOR_1,
    AN_SENSOR_2,
    AN_SENSOR_3,
    AN_SENSOR_4,
    AN_SENSOR_5
} adc_pin_func_t;

adc_pin_func_t a_particular_pin = ...

,是否有可能检查 pin 是否是特定组的一部分,例如 pin 是 的一部分AN_MOTOR或一部分AN_SENSOR,而不是必须检查每个可能组中的每个项目。

或者除了使用枚举之外,还有更有效的方法吗?

提前致谢

4

6 回答 6

22

您可以为每个组创建掩码:

typedef enum {
    AN_TRISTATE_0     = 0x00001,
    AN_TRISTATE_1     = 0x00002,
    AN_TRISTATE_MASK  = 0x0000f,

    AN_NOTHING        = 0x00010,    // Should this be 0x00000 ?

    AN_MOTOR_1        = 0x00100,
    AN_MOTOR_2        = 0x00200,
    AN_MOTOR_3        = 0x00400,
    AN_MOTOR_MASK     = 0x00f00,

    AN_SENSOR_1       = 0x01000,
    AN_SENSOR_2       = 0x02000,
    AN_SENSOR_3       = 0x04000,
    AN_SENSOR_4       = 0x08000,
    AN_SENSOR_5       = 0x10000,
    AN_SENSOR_MASK    = 0xff000
} adc_pin_func_t;

然后使用运算符简单地针对掩码测试一个组&

if (a_particular_pin & AN_SENSOR_MASK)
{
    // it's a sensor pin
}
else if (a_particular_pin & AN_MOTOR_MASK)
{
    // it's a motor pin
}

编辑:正如其他人建议使用范围,那么您可能会为测试创建一个宏,这将允许您更改测试的执行方式而无需更改代码(总是一件好事):

#define IS_AN_SENSOR(x) (((x) & AN_SENSOR_MASK) != 0)
#define IS_AN_MOTOR(x) (((x) & AN_MOTOR_MASK) != 0)
// etc.

然后测试变为:

if (IS_AN_SENSOR(a_particular_pin))
{
    // it's a sensor pin
}
else if (IS_AN_MOTOR(a_particular_pin))
{
    // it's a motor pin
}
// etc

如果您随后需要更改为使用范围,则只需更改宏(并且您显然需要定义范围最小值/最大值):

#define IS_AN_SENSOR(x) ((x) >= AN_SENSOR_START && (x) <= AN_SENSOR_END)
// etc
于 2013-06-21T07:41:06.383 回答
4

你可以自由选择你的枚举值,所以你可以做这样的事情

typedef enum {
    AN_TRISTATE_0 = 0x0001,
    AN_TRISTATE_1 = 0x0002,
    AN_NOTHING = 0x0000,
    AN_MOTOR_1 = 0x0010,
    AN_MOTOR_2 = 0x0020,
    AN_MOTOR_3 = 0x0030,
    AN_SENSOR_1 = 0x0100,
    AN_SENSOR_2 = 0x0200,
    AN_SENSOR_3, /*and so on*/
    AN_SENSOR_4,
    AN_SENSOR_5
} adc_pin_func_t;

然后您可以比较位以检查类别。例如,电机类型是唯一具有非零值的类别(AN_MOTOR_2 & 0x00F0)

于 2013-06-21T07:37:59.793 回答
3

你可以做一个

typedef enum {
    AN_TRISTATE_START,
    AN_TRISTATE_0 = AN_TRISTATE_START,
    AN_TRISTATE_1,
    AN_TRISTATE_END = AN_TRISTATE_1,

    AN_NOTHING,

    AN_MOTOR_START,
    AN_MOTOR_1 = AN_MOTOR_START,
    AN_MOTOR_2,
    AN_MOTOR_3,
    AN_MOTOR_END = AN_MOTOR_3,

    AN_SENSOR_START,
    AN_SENSOR_1 = AN_SENSOR_START,
    AN_SENSOR_2,
    AN_SENSOR_3,
    AN_SENSOR_4,
    AN_SENSOR_5,
    AN_SENSOR_END = AN_SENSOR_5
} adc_pin_func_t;

bool inline
is_sensor(int pin)
{
    return AN_SENSOR_START <= pin
                           && pin <= AN_SENSOR_END
}

然后在你的代码中

if ( is_sensor(pin) )
{
    /* body */
}

这样您就不必关心屏蔽特定值。如果组包含很多值,则可能很有用。

于 2013-06-21T12:30:36.750 回答
1

您可以以 2 的指数为枚举赋值。然后您可以简单地使用按位 AND 和 OR 掩码。所以你可以分配像 1,2,4,8,16,32... 这样的值。


typedef enum {
    AN_TRISTATE_0 = 1,
    AN_TRISTATE_1 = 2,
    AN_NOTHING = 4,
    AN_MOTOR_1 = 8,
    AN_MOTOR_2 = 16,
    AN_MOTOR_3 = 32,
    AN_SENSOR_1 = 64,
    AN_SENSOR_2 = 128,
    AN_SENSOR_3 = 256,
    AN_SENSOR_4 = 512,
    AN_SENSOR_5 = 1024
} adc_pin_func_t;

然后检查电机类型,您可以与 (32+16+8) = 56 进行与运算。因此pin & 56,如果非零表示它是电机类型。

于 2013-06-21T07:37:42.070 回答
0

如果您不想手动维护不重叠的值,那么您几乎可以自动为您处理所有这些。您唯一需要弄清楚的是组中的最大位数:

#define PIN_GROUP_SHIFT 4
#define GET_PIN_GROUP(x) (adc_pin_group_t)((y) >> PIN_GROUP_SHIFT)

#define PIN_GROUP_START(x) XX_GROUP_##x = ((GROUP_##x << PIN_GROUP_SHIFT) - 1),

enum {
    GROUP_TRISTATE,
    GROUP_NOTHING,
    GROUP_MOTOR,
    GROUP_SENSOR
} adc_pin_group_t;

typedef enum {
    PIN_GROUP_START(TRISTATE)
    AN_TRISTATE_0,
    AN_TRISTATE_1,

    PIN_GROUP_START(NOTHING)
    AN_NOTHING,

    PIN_GROUP_START(MOTOR)
    AN_MOTOR_1,
    AN_MOTOR_2,
    AN_MOTOR_3,

    PIN_GROUP_START(SENSOR)
    AN_SENSOR_1,
    AN_SENSOR_2,
    AN_SENSOR_3,
    AN_SENSOR_4,
    AN_SENSOR_5
} adc_pin_func_t;

要确定枚举中条目的类型,请使用GET_PIN_GROUP(x)并将其与adc_pin_group_t枚举的任何值进行比较。如果有帮助,您甚至可以switch根据结果进行分析。

但是,该AN_NOTHING条目让我想知道您的枚举是否旨在与每个条目的特定值对齐。是与引脚相关的特定值,您可能无法任意分配。在这种情况下,您可能需要尝试一些复杂的东西(我没有测试过):

#define GET_PIN_VALUE(x) ((x) & ((1 << PIN_GROUP_SHIFT) - 1)
#define PIN_GROUP_START(x) \
    WW_GROUP_##x, \
    XX_GROUP_##x = (GROUP_##x << PIN_GROUP_SHIFT) \
                 + GET_PIN_INDEX(WW_GROUP_##x) - 1,

如果您需要知道原始枚举将使用的值,请使用GET_PIN_INDEX(x).

于 2013-08-12T23:58:48.963 回答
0

如果你真的想在你的枚举中有一些模块化(“硬编码”枚举值也是一种有效的方法),你可以实现一个带有一些 OOP 风格的结构。设计变得更加复杂,但使用仍然很简单:

#include <stdio.h>
#include <string.h>

// Every enum will have its first value start at the value of the previous enum's last member PLUS ONE 
#define OFFSET_ENUM_MOTOR  (                        sizeof(adc_pin_tristate_t) )
#define OFFSET_ENUM_SENSOR ( OFFSET_ENUM_MOTOR   +  sizeof(adc_pin_motor_t)    )


///////////////////////////////////////////////////////////////////////////////
// Enum
typedef enum {
    AN_TRISTATE_0,
    AN_TRISTATE_1,
    AN_NOTHING
} adc_pin_tristate_t;

typedef enum {
    AN_MOTOR_1 = OFFSET_ENUM_MOTOR,
    AN_MOTOR_2,
    AN_MOTOR_3
} adc_pin_motor_t;

typedef enum {
    AN_SENSOR_1 = OFFSET_ENUM_SENSOR,
    AN_SENSOR_2,
    AN_SENSOR_3,
    AN_SENSOR_4,
    AN_SENSOR_5
} adc_pin_sensor_t;
///////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////////
// Struct for abstraction
typedef struct adc_pin_func2_t{

    // our "enum value"
    unsigned int enum_id;

    // return is the enum is a motor one 
    int(*isMotor)(struct adc_pin_func2_t*);

} adc_pin_func2_t;
// Struct
///////////////////////////////////////////////////////////////////////////////


// Member methods : return if the enum is a motor one
int
PinFunc_isMotor(
    adc_pin_func2_t *This /* object */
    )
{
    return ( (This->enum_id>=OFFSET_ENUM_MOTOR) && (This->enum_id<OFFSET_ENUM_SENSOR) );
}

// Creation of the structure

// Initialization
static void 
PinFunc_Init(
        adc_pin_func2_t *This, /* output */
        unsigned int identifier /* old enum identifier */ 
            )
{
    // copy members
    This->enum_id = identifier;

    //copy methods (do not forget to do it !)
    This->isMotor = PinFunc_isMotor;


}

// Constructor
adc_pin_func2_t 
PinFunc_Create(
        unsigned int identifier /* old enum identifier */ 
              )
{
   adc_pin_func2_t This;
   PinFunc_Init(&This, identifier);

   return This;
}


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
main()
{
   adc_pin_func2_t pin = PinFunc_Create(AN_NOTHING);
   printf("%d \n", pin );
   printf("%d \n", pin.isMotor(&pin) );

   adc_pin_func2_t pin2 = PinFunc_Create(AN_MOTOR_2);
   printf("%d \n", pin2 );
   printf("%d \n", pin2.isMotor(&pin2) );
}

成员函数 like 的使用pin.isMotor(&pin)不是很优雅(我们重复 pin),但它是 C 的一个缺点,它不是 OOP 语言。

于 2013-06-21T08:15:42.780 回答