创建嵌套的 If 和 else 定义 C 编程

Create Nested If and else Define C Programming

我需要一些帮助。 我想为位操作创建一个#define。另外,对于位操作本身,我想检查大小以确保我正在执行具有相同数据类型大小的位操作。

所以我在这里尝试的是:

#define bitset(byte,nbit)  (sizeof(nbit) <= 2 ? (sizeof(nbit) == 2 ?  ((byte) |=  ((uint16)1<<(nbit))) : ( (byte) |=  ((uint8)1<<(nbit)))) \
                                      : (sizeof(nbit) == 8  ?  ((byte) |=  ((uint64)1<<(nbit))) : ( (byte) |=  ((uint32)1<<(nbit)))\

我做了某事吗?错误的 ?甚至可以创建这样的定义吗?

Is this define correct ?

不,你犯了一些错误。

首先,我相信你想检查 sizeof(byte) 而不是代表位数的变量的大小...

它应该是 == 8 ? ((byte) |= ((uint64)1<<(nbit)),这样当 byte8 个字节时,uint64_t 被选中。

您错过了定义末尾的 \ 以将其加入下一行。

你错过了最后两个 )) 来关闭打开的。

没有uint8也没有uint64等。从stdint.huint16_tuint8_t等类型。使用标准类型。

但是请考虑更清晰的格式:

#define bitset(byte,nbit)  ( \
      sizeof(byte) == 1 ? ((byte) |= (uint8_t)1<<(nbit)) : \
      sizeof(byte) == 2 ? ((byte) |= (uint16_t)1<<(nbit)) : \
      sizeof(byte) == 4 ? ((byte) |= (uint32_t)1<<(nbit)) : \
      ((byte) |=  (uint64_t)1<<(nbit)) \
)

Is it even possible to create such a define ?

当然是。如果您不关心 return 值并且表达式不必是常量表达式,那么您甚至可以使用旧的 do { ... } while(0) 技巧(实际上是约定)编写完整的语句:

#define bitset(byte,nbit)  do { \
    static_assert(sizeof(byte) == 1 || \
            sizeof(byte) == 2 || \
            sizeof(byte) == 4 || \
            sizeof(byte) == 8, \
            "nbit has wrong size"); \
    assert(nbit < sizeof(byte) * CHAR_BIT); /* right? */ \
    switch (sizeof(byte)) { \
        case 1: (byte) |=  (uint8_t)1<<(nbit); break; \
        case 2: (byte) |=  (uint16_t)1<<(nbit); break; \
        case 4: (byte) |=  (uint32_t)1<<(nbit); break; \
        case 8: (byte) |=  (uint64_t)1<<(nbit); break; \
    } \
} while(0)

或类似的。您还可以探索 _Generic 并使您的代码仅显式接受您想要的这些类型:

void bitset_8(uint8_t *byte, unsigned nbit) {
    *byte |= (uint8_t)1<<nbit;
}
void bitset_16(uint16_t *byte, unsigned nbit) {
    *byte |= (uint16_t)1<<nbit;
}
void bitset_32(uint32_t *byte, unsigned nbit) {
    *byte |= (uint32_t)1<<nbit;
}
void bitset_64(uint64_t *byte, unsigned nbit) {
    *byte |= (uint64_t)1<<nbit;
}
#define bitset(byte,nbit)  (_Generic((byte), \
    uint8_t: bitset_8, \
    uint16_t: bitset_16, \
    uint32_t: bitset_32, \
    uint64_t: bitset_64)(&byte, nbit))

总而言之,这个功能只是一个例子。在实际代码中我无论如何都会写:

#define bitset(byte,nbit)   ((byte) |= 1ull<<(nbyte))

因为我相信编译器会足够聪明来内联表达式并且编译器会优化,如果 byte 有例如 8 位,那么就不需要使用完整的 64 位算法,它会使用 8 个字节。