上下文:
我有一些使用了很多位标志的C代码。旗子组可能有几百名成员。目前,这些标志被定义为必须应用于特定元素的32位掩码。
/* Flags: */
#define OF1_RESIST_FIRE 0x00000001L
#define OF1_RESIST_COLD 0x00000002L
#define OF1_RESIST_ACID 0x00000004L
...
#define OF2_SUSTAIN_STRENGTH 0x00000001L
...
#define OF9_AGGRAVATES_CATS 0x00000004L
/* Bitset: */
uint32_t oflags1;
uint32_t oflags2;
...为了便于管理,我希望将标志改为位索引,并将标志合并为数组,例如:
/* Flags: */
enum object_flags {
RESIST_FIRE,
RESIST_COLD,
RESIST_ACID,
...
SUSTAIN_STRENGTH,
...
AGGRAVATES_CATS,
...
MAX_OBJECT_FLAGS,
};
/* Bitset: */
BITSET_DECLARE(oflags, MAX_OBJECT_FLAGS); // uint32_t oflags[9];(注:以上代码是上下文说明性的,而不是供审阅的)。
代码:
为此,我创建了一些宏来帮助操纵位集数组,其基础是本公司常见问题解答项目 (b根s.h):
#pragma once
#include
#include
/*
* Macros to simplify creating and using bit flags.
*
* Flags are stored in an array of uint32_t, the size of which
* is determined by the required number of bits.
*
* Any bits after the required size may change during operation.
*/
/* The underlying type of the array */
#define BFLAGS_WORD_T uint32_t
/* The number of bits in the underlying type */
#define BFLAGS_WORD_BIT_SIZE (sizeof(BFLAGS_WORD_T) * CHAR_BIT)
/* The number of elements in the array */
#define BFLAGS_ARRAY_SIZE(bits) \
(((bits) + BFLAGS_WORD_BIT_SIZE - 1) / BFLAGS_WORD_BIT_SIZE)
/* Get the array element containing this bit */
#define BFLAGS_WORD_INDEX(bit) ((bit) / BFLAGS_WORD_BIT_SIZE)
/* Create a mask for this bit in the array element that contains it */
#define BFLAGS_WORD_MASK(bit) (1 << ((bit) % BFLAGS_WORD_BIT_SIZE))
/* Declare a bit flag array containing enough elements to
* store the requested number of bits. */
#define BFLAGS_DECLARE(bflags, bits) \
BFLAGS_WORD_T bflags[BFLAGS_ARRAY_SIZE(bits)]
/* As BFLAGS_DECLARE, but also zeros the array contents.
* Prefer to use this where possible. */
#define BFLAGS_DECLARE_ZERO(bflags, bits) \
BFLAGS_WORD_T bflags[BFLAGS_ARRAY_SIZE(bits)] = { 0 }
/* Set all bits in the array to 0 */
#define BFLAGS_ZERO(bflags, bits) \
do { \
for (size_t i = 0; i != BFLAGS_ARRAY_SIZE(bits); ++i) \
(bflags)[i] = (BFLAGS_WORD_T)0; \
} while (false)
/* Set all bits in the array to 1 */
#define BFLAGS_FILL(bflags, bits) \
do { \
for (size_t i = 0; i != BFLAGS_ARRAY_SIZE(bits); ++i) \
(bflags)[i] = ~(BFLAGS_WORD_T)0; \
} while (false)
/* Copy to another array */
#define BFLAGS_COPY(bflags_out, bflags_a, bits) \
do { \
for (size_t i = 0; i != BFLAGS_ARRAY_SIZE(bits); ++i) \
(bflags_out)[i] = (bflags_a)[i]; \
} while (false)
/* Test two arrays for equality.
* Bits of the last array element may differ after the last bit
* so we mask them out before comparing. */
#define BFLAGS_EQ(eq_out, bflags_a, bflags_b, bits) \
do { \
eq_out = true; \
for (size_t i = 0; i != BFLAGS_ARRAY_SIZE(bits) - 1; ++i) \
eq_out &= ((bflags_a)[i] == (bflags_b)[i]); \
BFLAGS_WORD_T mask = (~(BFLAGS_WORD_T)0) >> ((BFLAGS_WORD_BIT_SIZE - ((bits) % BFLAGS_WORD_BIT_SIZE)) % BFLAGS_WORD_BIT_SIZE); \
eq_out &= (((bflags_a)[BFLAGS_ARRAY_SIZE(bits) - 1] & mask) == ((bflags_b)[BFLAGS_ARRAY_SIZE(bits) - 1] & mask)); \
} while (false)
/* Set the specified bit to 1 */
#define BFLAGS_SET(bflags, bit) ((bflags)[BFLAGS_WORD_INDEX(bit)] |= BFLAGS_WORD_MASK(bit))
/* Set the specified bit to 0 */
#define BFLAGS_CLEAR(bflags, bit) ((bflags)[BFLAGS_WORD_INDEX(bit)] &= ~BFLAGS_WORD_MASK(bit))
/* Toggle the specified bit */
#define BFLAGS_FLIP(bflags, bit) ((bflags)[BFLAGS_WORD_INDEX(bit)] ^= BFLAGS_WORD_MASK(bit))
/* Check the value of the specified bit */
#define BFLAGS_TEST(bflags, bit) (((bflags)[BFLAGS_WORD_INDEX(bit)] & BFLAGS_WORD_MASK(bit)) != 0)
/* Do a bitwise-and of the specified bit flag arrays and put the result
* in bflags_out. All the flag sets should contain the same number of bits. */
#define BFLAGS_AND(bflags_out, bflags_a, bflags_b, bits) \
do { \
for (size_t i = 0; i != BFLAGS_ARRAY_SIZE(bits); ++i) \
(bflags_out)[i] = (bflags_a)[i] & (bflags_b)[i]; \
} while (false)
/* Do a bitwise-or of the specified bit flag arrays and put the result
* in bflags_out. All the flag sets should contain the same number of bits. */
#define BFLAGS_OR(bflags_out, bflags_a, bflags_b, bits) \
do { \
for (size_t i = 0; i != BFLAGS_ARRAY_SIZE(bits); ++i) \
(bflags_out)[i] = (bflags_a)[i] | (bflags_b)[i]; \
} while (false)
/* Do a bitwise-xor of the specified bit flag arrays and put the result
* in bflags_out. All the flag sets should contain the same number of bits. */
#define BFLAGS_XOR(bflags_out, bflags_a, bflags_b, bits) \
do { \
for (size_t i = 0; i != BFLAGS_ARRAY_SIZE(bits); ++i) \
(bflags_out)[i] = (bflags_a)[i] ^ (bflags_b)[i]; \
} while (false)
/* Do a bitwise-not of the specified bit flag array and put the result
* in bflags_out. Both the flag sets should contain the same number of bits. */
#define BFLAGS_NOT(bflags_out, bflags_a, bits) \
do { \
for (size_t i = 0; i != BFLAGS_ARRAY_SIZE(bits); ++i) \
(bflags_out)[i] = ~(bflags_a)[i]; \
} while (false)任何反馈意见都是受欢迎的,但特别是关于:
BFLAGS_EQ的结果,而不是传递它呢?单元测试:
#include "bflags.h"
#include
#include
#include
#define UNUSED(x) __attribute((unused)) x
#define mu_assert(test) do { if (!(test)) return #test; } while (0)
#define mu_run_test(test) do { char *message = test(); tests_run++; if (message) return message; } while (0)
extern int tests_run;
static char* bflags_test_declare()
{
{
//BFLAGS_DECLARE(bflags, 0); // won't compile (size 0 array)
}
{
BFLAGS_DECLARE(bflags, 1);
static_assert(sizeof(bflags) / sizeof(bflags[0]) == 1, "");
}
{
BFLAGS_DECLARE(bflags, 32);
static_assert(sizeof(bflags) / sizeof(bflags[0]) == 1, "");
}
{
BFLAGS_DECLARE(bflags, 33);
static_assert(sizeof(bflags) / sizeof(bflags[0]) == 2, "");
}
return NULL;
}
static char* bflags_test_declare_zero()
{
{
BFLAGS_DECLARE_ZERO(bflags, 1);
mu_assert(bflags[0] == 0);
}
{
BFLAGS_DECLARE_ZERO(bflags, 320);
for (size_t i = 0; i != BFLAGS_ARRAY_SIZE(320); ++i)
mu_assert(bflags[i] == 0);
}
return NULL;
}
static char* bflags_zero()
{
{
BFLAGS_DECLARE(bflags, 32);
bflags[0] = 0xffffffff;
BFLAGS_ZERO(bflags, 32);
mu_assert(bflags[0] == 0);
}
{
BFLAGS_DECLARE(bflags, 321);
for (size_t i = 0; i != BFLAGS_ARRAY_SIZE(321); ++i)
bflags[i] = (BFLAGS_WORD_T)i;
mu_assert(bflags[1] == 1);
BFLAGS_ZERO(bflags, 321);
for (size_t i = 0; i != BFLAGS_ARRAY_SIZE(321); ++i)
mu_assert(bflags[i] == 0);
}
return NULL;
}
static char* bflags_fill()
{
{
BFLAGS_DECLARE_ZERO(bflags, 32);
BFLAGS_FILL(bflags, 32);
mu_assert(bflags[0] == 0xffffffff);
}
{
BFLAGS_DECLARE_ZERO(bflags, 35);
BFLAGS_FILL(bflags, 35);
mu_assert(bflags[0] == 0xffffffff);
// values above bit size are also set, but we shouldn't depend on it!
for (size_t i = 0; i != 35; ++i)
mu_assert(BFLAGS_TEST(bflags, i) != 0);
}
return NULL;
}
static char* bflags_copy()
{
{
BFLAGS_DECLARE_ZERO(bflags_a, 59);
for (size_t i = 0; i != 59; ++i)
if (i % 6 == 0)
BFLAGS_SET(bflags_a, i);
BFLAGS_DECLARE_ZERO(bflags_b, 59);
BFLAGS_COPY(bflags_b, bflags_a, 59);
for (size_t i = 0; i != 59; ++i)
if (i % 6 == 0)
mu_assert(BFLAGS_TEST(bflags_b, i));
else
mu_assert(!BFLAGS_TEST(bflags_b, i));
}
return NULL;
}
static char* bflags_eq()
{
{
BFLAGS_DECLARE_ZERO(bflags_a, 32);
BFLAGS_DECLARE_ZERO(bflags_b, 32);
{
bool eq = false;
BFLAGS_EQ(eq, bflags_a, bflags_b, 32);
mu_assert(eq);
}
BFLAGS_SET(bflags_a, 25);
{
bool eq = false;
BFLAGS_EQ(eq, bflags_a, bflags_b, 32);
mu_assert(!eq);
}
}
{
BFLAGS_DECLARE_ZERO(bflags_a, 59);
for (size_t i = 0; i != 59; ++i)
if (i % 6 == 0)
BFLAGS_SET(bflags_a, i);
BFLAGS_DECLARE_ZERO(bflags_b, 59);
BFLAGS_COPY(bflags_b, bflags_a, 59);
{
bool eq = false;
BFLAGS_EQ(eq, bflags_a, bflags_b, 59);
mu_assert(eq);
}
BFLAGS_SET(bflags_a, 60); // set a bit after the end...
{
bool eq = false;
BFLAGS_EQ(eq, bflags_a, bflags_b, 59);
mu_assert(eq);
}
}
return NULL;
}
static char* bflags_set()
{
{
BFLAGS_DECLARE_ZERO(bflags, 32);
BFLAGS_SET(bflags, 0);
mu_assert(bflags[0] == (1 << 0));
BFLAGS_SET(bflags, 5);
mu_assert(bflags[0] == ((1 << 0) | (1 << 5)));
BFLAGS_SET(bflags, 31);
mu_assert(bflags[0] == ((1 << 0) | (1 << 5) | (1 << 31)));
}
{
BFLAGS_DECLARE_ZERO(bflags, 64);
BFLAGS_SET(bflags, 0);
mu_assert(bflags[0] == (1 << 0));
BFLAGS_SET(bflags, 63);
mu_assert(bflags[1] == (1 << 31));
}
{
BFLAGS_DECLARE_ZERO(bflags, 32);
BFLAGS_SET(bflags, 12);
mu_assert(bflags[0] == (1 << 12));
BFLAGS_SET(bflags, 12);
mu_assert(bflags[0] == (1 << 12));
}
return NULL;
}
static char* bflags_clear()
{
{
BFLAGS_DECLARE_ZERO(bflags, 32);
BFLAGS_FILL(bflags, 32);
BFLAGS_CLEAR(bflags, 5);
mu_assert(bflags[0] == ~(1 << 5));
BFLAGS_CLEAR(bflags, 0);
mu_assert(bflags[0] == ~((1 << 0) | (1 << 5)));
}
{
BFLAGS_DECLARE_ZERO(bflags, 35);
BFLAGS_FILL(bflags, 35);
mu_assert(BFLAGS_TEST(bflags, 31));
mu_assert(BFLAGS_TEST(bflags, 32));
BFLAGS_CLEAR(bflags, 32);
mu_assert(!BFLAGS_TEST(bflags, 32));
mu_assert(bflags[0] == ~(BFLAGS_WORD_T)0);
BFLAGS_CLEAR(bflags, 33);
mu_assert(!BFLAGS_TEST(bflags, 33));
mu_assert(bflags[0] == ~(BFLAGS_WORD_T)0);
}
{
BFLAGS_DECLARE_ZERO(bflags, 32);
BFLAGS_FILL(bflags, 32);
BFLAGS_CLEAR(bflags, 16);
mu_assert(bflags[0] == ~(1 << 16));
BFLAGS_CLEAR(bflags, 16);
mu_assert(!BFLAGS_TEST(bflags, 16));
}
return NULL;
}
static char* bflags_flip()
{
{
BFLAGS_DECLARE_ZERO(bflags, 32);
BFLAGS_FLIP(bflags, 13);
mu_assert(bflags[0] == (1 << 13));
BFLAGS_FLIP(bflags, 13);
mu_assert(bflags[0] == 0);
}
{
BFLAGS_DECLARE_ZERO(bflags, 72);
BFLAGS_FLIP(bflags, 68);
mu_assert(bflags[0] == 0 && bflags[1] == 0);
mu_assert(BFLAGS_TEST(bflags, 68));
}
return NULL;
}
static char* bflags_test()
{
{
BFLAGS_DECLARE_ZERO(bflags, 128);
mu_assert(!BFLAGS_TEST(bflags, 53));
mu_assert(!BFLAGS_TEST(bflags, 125));
BFLAGS_FLIP(bflags, 53);
BFLAGS_FLIP(bflags, 125);
mu_assert(BFLAGS_TEST(bflags, 53));
mu_assert(BFLAGS_TEST(bflags, 125));
}
return NULL;
}
static char* bflags_and()
{
{
BFLAGS_DECLARE_ZERO(bflags_a, 64);
BFLAGS_DECLARE_ZERO(bflags_b, 64);
BFLAGS_DECLARE_ZERO(bflags_c, 64);
BFLAGS_FILL(bflags_a, 64);
BFLAGS_AND(bflags_c, bflags_a, bflags_b, 64);
for (size_t i = 0; i != 64; ++i)
mu_assert(!BFLAGS_TEST(bflags_c, i));
}
{
BFLAGS_DECLARE_ZERO(bflags_a, 64);
BFLAGS_DECLARE_ZERO(bflags_c, 64);
BFLAGS_FILL(bflags_a, 64);
BFLAGS_AND(bflags_c, bflags_a, bflags_a, 64);
for (size_t i = 0; i != 64; ++i)
mu_assert(BFLAGS_TEST(bflags_c, i));
}
{
BFLAGS_DECLARE_ZERO(bflags_a, 64);
BFLAGS_DECLARE_ZERO(bflags_b, 64);
BFLAGS_DECLARE_ZERO(bflags_c, 64);
for (size_t i = 0; i != 64; ++i)
if (i % 2 == 0)
BFLAGS_SET(bflags_a, i);
for (size_t i = 0; i != 64; ++i)
if (i % 2 != 0)
BFLAGS_SET(bflags_b, i);
BFLAGS_AND(bflags_c, bflags_a, bflags_b, 64);
for (size_t i = 0; i != 64; ++i)
mu_assert(!BFLAGS_TEST(bflags_c, i));
}
return NULL;
}
static char* bflags_or()
{
{
BFLAGS_DECLARE_ZERO(bflags_a, 64);
BFLAGS_DECLARE_ZERO(bflags_b, 64);
BFLAGS_DECLARE_ZERO(bflags_c, 64);
BFLAGS_FILL(bflags_a, 64);
BFLAGS_OR(bflags_c, bflags_a, bflags_b, 64);
for (size_t i = 0; i != 64; ++i)
mu_assert(BFLAGS_TEST(bflags_c, i));
}
{
BFLAGS_DECLARE_ZERO(bflags_a, 64);
BFLAGS_DECLARE_ZERO(bflags_c, 64);
BFLAGS_FILL(bflags_a, 64);
BFLAGS_OR(bflags_c, bflags_a, bflags_a, 64);
for (size_t i = 0; i != 64; ++i)
mu_assert(BFLAGS_TEST(bflags_c, i));
}
{
BFLAGS_DECLARE_ZERO(bflags_a, 64);
BFLAGS_DECLARE_ZERO(bflags_b, 64);
BFLAGS_DECLARE_ZERO(bflags_c, 64);
for (size_t i = 0; i != 64; ++i)
if (i % 2 == 0)
BFLAGS_SET(bflags_a, i);
for (size_t i = 0; i != 64; ++i)
if (i % 2 != 0)
BFLAGS_SET(bflags_b, i);
BFLAGS_OR(bflags_c, bflags_a, bflags_b, 64);
for (size_t i = 0; i != 64; ++i)
mu_assert(BFLAGS_TEST(bflags_c, i));
}
return NULL;
}
static char* bflags_xor()
{
{
BFLAGS_DECLARE_ZERO(bflags_a, 64);
BFLAGS_DECLARE_ZERO(bflags_b, 64);
BFLAGS_DECLARE_ZERO(bflags_c, 64);
BFLAGS_FILL(bflags_a, 64);
BFLAGS_XOR(bflags_c, bflags_a, bflags_b, 64);
for (size_t i = 0; i != 64; ++i)
mu_assert(BFLAGS_TEST(bflags_c, i));
}
{
BFLAGS_DECLARE_ZERO(bflags_a, 64);
BFLAGS_DECLARE_ZERO(bflags_c, 64);
BFLAGS_FILL(bflags_a, 64);
BFLAGS_XOR(bflags_c, bflags_a, bflags_a, 64);
for (size_t i = 0; i != 64; ++i)
mu_assert(!BFLAGS_TEST(bflags_c, i));
}
{
BFLAGS_DECLARE_ZERO(bflags_a, 64);
BFLAGS_DECLARE_ZERO(bflags_b, 64);
BFLAGS_DECLARE_ZERO(bflags_c, 64);
for (size_t i = 0; i != 64; ++i)
if (i % 2 == 0)
BFLAGS_SET(bflags_a, i);
for (size_t i = 0; i != 64; ++i)
if (i % 2 != 0)
BFLAGS_SET(bflags_b, i);
BFLAGS_XOR(bflags_c, bflags_a, bflags_b, 64);
for (size_t i = 0; i != 64; ++i)
mu_assert(BFLAGS_TEST(bflags_c, i));
}
return NULL;
}
static char* bflags_not()
{
{
BFLAGS_DECLARE_ZERO(bflags_a, 64);
BFLAGS_DECLARE_ZERO(bflags_b, 64);
for (size_t i = 0; i != 64; ++i)
if (i % 2 == 0)
BFLAGS_SET(bflags_a, i);
BFLAGS_NOT(bflags_b, bflags_a, 64);
for (size_t i = 0; i != 64; ++i)
if (i % 2 == 0)
mu_assert(!BFLAGS_TEST(bflags_b, i));
else
mu_assert(BFLAGS_TEST(bflags_b, i));
}
{
BFLAGS_DECLARE_ZERO(bflags_a, 64);
for (size_t i = 0; i != 64; ++i)
if (i % 2 == 0)
BFLAGS_SET(bflags_a, i);
BFLAGS_NOT(bflags_a, bflags_a, 64);
for (size_t i = 0; i != 64; ++i)
if (i % 2 == 0)
mu_assert(!BFLAGS_TEST(bflags_a, i));
else
mu_assert(BFLAGS_TEST(bflags_a, i));
}
return NULL;
}
static char* run_all_tests()
{
mu_run_test(bflags_test_declare);
mu_run_test(bflags_test_declare_zero);
mu_run_test(bflags_zero);
mu_run_test(bflags_fill);
mu_run_test(bflags_copy);
mu_run_test(bflags_eq);
mu_run_test(bflags_set);
mu_run_test(bflags_clear);
mu_run_test(bflags_flip);
mu_run_test(bflags_test);
mu_run_test(bflags_and);
mu_run_test(bflags_or);
mu_run_test(bflags_xor);
mu_run_test(bflags_not);
return NULL;
}
int tests_run = 0;
int main(int UNUSED(argc), char** UNUSED(argv))
{
char* result = run_all_tests();
if (result)
printf("TEST FAILED: %s\n", result);
else
printf("PASS\n");
printf("\ndone! %d tests run\n", tests_run);
return (result != NULL);
}谢谢!
发布于 2019-03-04 12:22:39
小的可移植性错误:如果我们在宏中使用false,那么bflags.h应该包括。或者使用0而不是false。
明确的可移植性错误:我们在推广之前转移了一个(签名的) int:
#定义BFLAGS_WORD_MASK(位) (1 << ((位)% BFLAGS_WORD_BIT_SIZE))
我认为我们首先需要适当类型的1:
#define BFLAGS_WORD_MASK(bit) ((BFLAGS_WORD_T)1 << ((bit) % BFLAGS_WORD_BIT_SIZE))同样,这个测试:
BFLAGS\_SET(bflags, 31); mu\_assert(bflags[0] == ((1 << 0) | (1 << 5) | (1 << 31)));
需求
BFLAGS_SET(bflags, 31);
mu_assert(bflags[0] == ((1 << 0) | (1 << 5) | (1ul << 31)));还有很多是我在gcc -Wall -Wextra上学到的,而且很容易修复。
另外,让我们了解一下const char* --所有的测试结果都应该是指向const的,修复它并不会有什么影响。
我看到的最后一个编译警告来自char** UNUSED(argv) --通过将它更改为UNUSED(char** argv)很容易修复。但是由于我们忽略了这两个参数,我们可以使用另一个合法签名:int main(void)。
就风格而言,我们可以使用typedef而不是BFLAGS_WORD_T的#define。与可选的固定宽度类型不同,我们可能应该使用uint_fast32_t,因为我们并不介意uint32_t是否不存在(在一些外来的或古老的体系结构上)。事实上,我们可能更喜欢普通的unsigned int,因为这应该是硬件的“自然”(最有效)整数大小。代码中的所有内容似乎都有适当的适应性,除了一些硬编码32位假设的测试。
顺便说一句,如果使用typedef,请记住以_t结尾的名称是为库保留的。
当用户可能将普通的int类型而不是无符号类型作为参数传递时,我确实对宏(而不是函数)的使用有所保留--例如,如果我们向无符号的BFLAGS_WORD_BIT_SIZE添加一个有符号的bits,那么在D28中就会得到不必要的提升。也许这些应该是简单的(不可见的)函数,给我们很强的打字能力?
我们可以在此减少重复:
#定义BFLAGS_DECLARE(b标志,位)\ BFLAGS_WORD_T b标志#定义BFLAGS_DECLARE_ZERO(b标志,位)\ BFLAGS_WORD_T bits={0}
就像这样:
#define BFLAGS_DECLARE_ZERO(bflags, bits) \
BFLAGS_DECLARE(bflags, bits) = { 0 }发布于 2019-03-08 13:14:50
最严重的问题:
1<的含义。您不能假设他们会理解BFLAGS_WORD_MASK的含义。这只不过是混淆了本来应该是清晰代码的东西。因此,我强烈建议你放弃这个想法。很多人还没试过这件事,结果总是很糟糕。全局问题:
0x00000001L创建类型为long的带符号整数常量。您不应该在按位操作时使用带符号类型。将此更改为0x00000001UL。危险在于,当符号位被意外设置时,符号类型可能会调用未定义的行为错误。而且几乎没有理由在符号类型上使用位运算符。此外,键入所有十六进制常量的零是很危险的,因为它们实际上没有任何意义,也不像预期的那样产生32位数。这样你就能得到真正的讨厌的虫子。例如,假设我们有一个16位系统,并键入以下内容:#define 0x00007FFF //这是类型有符号的int 16位#define 0x00008000 //这是类型无符号的int 16位#define BLUP 0x00010000 //这是长32位类型,您可以这样得到非常微妙的bug。去过那里,很难找到。用UL后缀所有这些十六进制常量。出于同样的原因,枚举不应该用于按位操作,因为枚举常量总是int,编译器不能在不违反C标准的情况下更改类型。因此,您不应该为此使用枚举。您不应该将long或unsigned long常量存储在枚举中,因为它们将被转换为错误和糟糕的int。以上所述意味着您的整个代码必须从头开始重写。
其他问题:
避免位移位1,因为它是类型的int,并可能产生与上述相同的问题。使用1u代替。不要将C中的函数声明为static char* bflags_or(),而是使用static char* bflags_or (void)。空括号()的意思是“接受任何类型”,这不是您想要的。这种样式在C标准中被标记为过时,可以在任何时候删除。没有理由使用非标准的int UNUSED(argc).相反,编写以下内容: int (int,char** argv) { (void) argc;(void)argv;这是100%的可移植性和标准,实现了与未使用的非标准一样的功能。不要使用非标准的#pragma once,使用经典的标题保护#ifndef SOMETHING_H #define SOMETHING_H ... #endif。100%便携和标准。一般避免使用语用。风格评论:
无论主体包含多少行,在if和循环之后始终使用复合语句D42是很好的做法。这减少了缩进和维护相关错误的数量。另外,如果不允许没有do-while(0)的选择/循环语句,则不必再使用{}宏技巧。https://codereview.stackexchange.com/questions/214634
复制相似问题