将2个枚举与数学运算符组合在一起

时间:2014-01-25 03:17:57

标签: c enums

我有这个枚举:

enum bus {
    MEDIA_BUS_UNKNOWN, 
    MEDIA_BUS_VIRTUAL = 1 << 1,
    MEDIA_BUS_PCI = 1 << 2,
    MEDIA_BUS_USB = 1 << 3,
};

enum bus get_bus( char *sys )
{
    FILE *fd;
    char file[PATH_MAX];
    char s[1024];

    if(!strcmp(sys, "/sys/devices/virtual"))
        return MEDIA_BUS_VIRTUAL;

    snprintf(file, PATH_MAX, "%s/modalias", sys);
    fd = fopen(file, "r");
    if(!fd)
        return MEDIA_BUS_UNKNOWN;
    if(!fgets(s, sizeof(s), fd)) {
        fclose(fd);
        return MEDIA_BUS_UNKNOWN;
    }
    fclose(fd);

    if(!strncmp(s, "pci", 3))
        return MEDIA_BUS_PCI;
    if(!strncmp(s, "usb", 3))
        return MEDIA_BUS_USB;

    return MEDIA_BUS_UNKNOWN;

}

我想创建一个函数来返回带有pci或usb总线的设备:

const char *get_device(const enum bus desired_bus)
{
    enum bus bus;
...................................................
    for( i = 0; i < md->md_size; i++, md_ptr++ ) {
        bus = get_bus( md_ptr->sys );
        if( ( bus & desired_bus ) == desired_bus )
                return md_ptr->node;
}

并调用此函数返回设备:

get_device(const enum bus desired_bus)

如果请求是针对具有pci或usb总线类型的设备:

get_device(MEDIA_BUS_PCI | MEDIA_BUS_USB);

可以将数学运算符用于枚举吗?

3 个答案:

答案 0 :(得分:1)

当然你可以使用数学运算符,但我相信你正在寻找bitwise operations,对吧?在这种情况下,您enum成员的值必须是2的幂,您可以像这样进行测试:if(desired_bus & MEDIA_BUS_PCI)如果先前desired_bus |= MEDIA_BUS_PCI已完成if }将具有MEDIA_BUS_PCI值,因此iftrue,表示该位已设置。

代码示例:

enum bus {
    MEDIA_BUS_UNKNOWN, 
    MEDIA_BUS_VIRTUAL = 1 << 1,
    MEDIA_BUS_PCI = 1 << 2,
    MEDIA_BUS_USB = 1 << 3,
};
/* set flags */
desired_bus |= (MEDIA_BUS_PCI | MEDIA_BUS_USB);

and then:

        /* test if flag MEDIA_BUS_PCI was requested.. */
       if(desired_bus & MEDIA_BUS_PCI)

如果未设置,我们会得到一个与我们的MEDIA_BUS_UNKNOWN值匹配的0值,我认为这是一个很好的误差。

编辑更完整的工作C示例:

enum bus {
    MEDIA_BUS_UNKNOWN, 
    MEDIA_BUS_VIRTUAL = 1 << 1,
    MEDIA_BUS_PCI = 1 << 2,
    MEDIA_BUS_USB = 1 << 3,
};

enum bus get_bus( const char *sys );

int main(int argc, char *argv[])
{
    const char *sym = argv[1];
    enum bus b = get_bus(sym);

    if(b & MEDIA_BUS_VIRTUAL)
        printf("MEDIA_BUS_VIRTUAL requested\n");
    if(b & MEDIA_BUS_USB)
        printf("MEDIA_BUS_USB requested\n");
    return 0;
}

enum bus get_bus( const char *sys )
{
    if(!strcmp("pci", sys))
        return MEDIA_BUS_VIRTUAL;
    if(!strcmp("usb", sys))
        return MEDIA_BUS_USB;
    if(!strcmp("pci&usb", sys))
        return MEDIA_BUS_VIRTUAL | MEDIA_BUS_USB;
    return MEDIA_BUS_UNKNOWN;
}

如果您使用以下命令调用已编译的程序:

a.exe usb:将输出:

MEDIA_BUS_USB requested

a.exe "pci&usb"将输出:

MEDIA_BUS_VIRTUAL requested
MEDIA_BUS_USB requested

注意:您可能需要使用类似unsigned而非enum bus的类型(最大尺寸为int)来保存一组enum bus值。

答案 1 :(得分:0)

是的,对于您的情况,您需要确保每个枚举值组合都是唯一的,并且很容易分解。要做到这一点,你应该让每个人都有两个明显的力量:

enum bus {
    MEDIA_BUS_UNKNOWN = 1,
    MEDIA_BUS_VIRTUAL = 2,
    MEDIA_BUS_PCI = 4,
    MEDIA_BUS_USB = 8,
};

(然后您可以通过撰写例如desired_bus & MEDIA_BUS_PCI来测试匹配。)

答案 2 :(得分:0)

这是个人品味的问题,但我发现使用枚举来控制位掩码而不是误导。

我宁愿用#define来做,以便能够轻松定义蒙版组合。例如:

#define MEDIA_BUS_UNKNOWN 0x00

#define MEDIA_BUS_GPU     0x10
#define MEDIA_BUS_CPU     0x20

#define MEDIA_BUS_VIRTUAL (0x1 | MEDIA_BUS_CPU)
#define MEDIA_BUS_PCI     (0x2 | MEDIA_BUS_CPU)
#define MEDIA_BUS_USB     (0x3 | MEDIA_BUS_CPU)
#define MEDIA_BUS_AGP     (0x4 | MEDIA_BUS_GPU)
#define MEDIA_BUS_PCIE    (0x5 | MEDIA_BUS_GPU)

#define MEDIA_BUS_PU_MASK   0x30 // to isolate the PU type 
#define MEDIA_BUS_TYPE_MASK 0x0F // to isolate the bus type 

typedef int bus_type;

(一个相当愚蠢的例子,但如果不偏离OP的问题,我找不到更好的方法)