创建嵌套的 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))
,这样当 byte
有 8
个字节时,uint64_t
被选中。
您错过了定义末尾的 \
以将其加入下一行。
你错过了最后两个 ))
来关闭打开的。
没有uint8
也没有uint64
等。从stdint.h
有uint16_t
和uint8_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 个字节。
我需要一些帮助。 我想为位操作创建一个#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))
,这样当 byte
有 8
个字节时,uint64_t
被选中。
您错过了定义末尾的 \
以将其加入下一行。
你错过了最后两个 ))
来关闭打开的。
没有uint8
也没有uint64
等。从stdint.h
有uint16_t
和uint8_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 个字节。