C、正确使用枚举、联合和函数return
C, proper use of enums, unions and function return
我的目标是实现最佳代码/设计实践:
我有 return 2 个可能的枚举的函数,可以是(状态枚举)或(错误枚举)。
为了区分这两个枚举,它们的值必须彼此相距很远并且从不重叠,例如:
其他模块具有预期的功能(错误枚举)。而且我不想制作从状态到错误的映射函数。所以我必须在(枚举状态)中包含(枚举错误)。
Enum eSomeState{
enum1Value = 0,
...
enum1Value99 = 99, // <<max
};
//defined in different module:
Enum eSomeError{
enum2Value = 100, // <<min
...
enum2Value99 = 199,
};
好像它们重叠了,不可能知道哪个是从被调用的函数中 returned 的(没有额外的标志)。
所以,在我的代码的前面,我曾经定义两个枚举,(将错误枚举中的所有错误组合)到(状态枚举).. 如下
版本 1:
/* used by this module */
enum eSomeState{
eSomeState_A = 1,
eSomeState_B = 2,
eSomeState_C = 3,
eSomeState_D = 4,
/* do not reach 100 */
/* DO NOT GO BELOW 100 */ <------------- copied from other module's enum
/* every time i update eSomeErrorFromOtherModule, i have to come here and update this as well */
eSomeStateError_ErrA = 100,
eSomeStateError_ErrB = 101,
eSomeStateError_ErrC = 102,
};
/* used by this module and other module that cares about error handling */
/* defined in different scope */
enum eSomeErrorFromOtherModule{
eSomeError_none = 0,
/* DO NOT GO BELOW 100 */
eSomeError_ErrA = 100,
eSomeError_ErrB = 101,
eSomeError_ErrC = 102,
};
bool doSomthingA( enum eSomeState* const state){
Assert(*state == eSomeState_A);
//do stuff
if (success){
*state = eSomeState_B;
return true;
}else{
*state = err;
}
return false;
}
来自其他模块的函数需要 (Error Enum) 类型,所以我曾经将 (State Enum) 转换为 (Error Enum)
一段时间后,我注意到每次我需要修改其中一个时,很难一直将(错误枚举)复制到(状态枚举)并保持它们相同。
所以我转到了版本 2:
/* used by this module */
enum eSomeState{
eSomeState_A = 1,
eSomeState_B = 2,
eSomeState_C = 3,
eSomeState_D = 4,
/* do not reach 100 */
}
union uSomeState{
enum eSomeState state;
enum eSomeErrorFromOtherModule err;
}
/* functions updated to */
bool doSomthingA( union eSomeState* const state){
Assert(state->state == eSomeState_A);
//do stuff
if (success){
state->state = eSomeState_B;
return true;
}else{
state->err = err;
}
return false;
}
版本 2 [我没有测试它,因为我几乎没有使用 union 但我希望它能工作] 减少了我的工作,将枚举从另一个模块复制到这个模块..但我仍然必须确保(状态枚举)不重叠(错误枚举)..
- 你对上面的代码有什么看法
- 您有什么建议可以进一步改进?
我喜欢将枚举视为常量的集合(列表)。如果我必须存储状态,那么我会引入一种新类型,例如bitset_t 或 state_t.
示例:
typedef int state_t;
enum someStates {};
enum someErrorStates {};
bool doSomething(state_t state) {}
因为有时需要 'combine' 两个状态在一起(例如通过运算符 '|'),这不在任一枚举的集合中。
个人意见。
补充:
基本上,枚举是一个 int(无符号?),您最多可以在一组中存储 INT_MAX 个值。但是如果你想要一个 'bitset',那么你只能使用 32 个不同的值(如果 int 是 32 位)。如果你想拥有更多,那么你必须实现一个bitset,一个单词数组。
示例:
#define word_size sizeof(unsigned int)
#define word_width (word_size * CHAR_BIT) // defined in limits.h
#define word_index(Pos) ((Pos) / word_width)
#define bit_index(Pos) ((Pos) % word_width)
unsigned int bitset[N];
bool isSet(unsigned int bs[N], unsigned int pos)
{
return ((bs[word_index(pos)] >> bit_index(pos)) & 1);
}
void setBit(unsigned int bs[N], unsigned int pos)
{
bs[word_index(pos)] |= (1 << bit_index(pos));
}
void clearBit(unsigned int bs[N], unsigned int pos)
{
bs[word_index(pos)] &= ~(1 << bit_index(pos));
}
void toggleBit(unsigned int bs[N], unsigned int pos)
{
bs[word_index(pos)] ^= (1 << bit_index(pos));
}
然后你可以这样定义你的枚举:
enum someState {
state1 = 1,
state2 = 2
//...
};
setBit(bitset, state2);
isSet(bitset, state2);
// ... and so on
基本上,枚举常量将描述位集中的(位)位置。
我的目标是实现最佳代码/设计实践:
我有 return 2 个可能的枚举的函数,可以是(状态枚举)或(错误枚举)。
为了区分这两个枚举,它们的值必须彼此相距很远并且从不重叠,例如:
其他模块具有预期的功能(错误枚举)。而且我不想制作从状态到错误的映射函数。所以我必须在(枚举状态)中包含(枚举错误)。
Enum eSomeState{
enum1Value = 0,
...
enum1Value99 = 99, // <<max
};
//defined in different module:
Enum eSomeError{
enum2Value = 100, // <<min
...
enum2Value99 = 199,
};
好像它们重叠了,不可能知道哪个是从被调用的函数中 returned 的(没有额外的标志)。
所以,在我的代码的前面,我曾经定义两个枚举,(将错误枚举中的所有错误组合)到(状态枚举).. 如下
版本 1:
/* used by this module */
enum eSomeState{
eSomeState_A = 1,
eSomeState_B = 2,
eSomeState_C = 3,
eSomeState_D = 4,
/* do not reach 100 */
/* DO NOT GO BELOW 100 */ <------------- copied from other module's enum
/* every time i update eSomeErrorFromOtherModule, i have to come here and update this as well */
eSomeStateError_ErrA = 100,
eSomeStateError_ErrB = 101,
eSomeStateError_ErrC = 102,
};
/* used by this module and other module that cares about error handling */
/* defined in different scope */
enum eSomeErrorFromOtherModule{
eSomeError_none = 0,
/* DO NOT GO BELOW 100 */
eSomeError_ErrA = 100,
eSomeError_ErrB = 101,
eSomeError_ErrC = 102,
};
bool doSomthingA( enum eSomeState* const state){
Assert(*state == eSomeState_A);
//do stuff
if (success){
*state = eSomeState_B;
return true;
}else{
*state = err;
}
return false;
}
来自其他模块的函数需要 (Error Enum) 类型,所以我曾经将 (State Enum) 转换为 (Error Enum)
一段时间后,我注意到每次我需要修改其中一个时,很难一直将(错误枚举)复制到(状态枚举)并保持它们相同。
所以我转到了版本 2:
/* used by this module */
enum eSomeState{
eSomeState_A = 1,
eSomeState_B = 2,
eSomeState_C = 3,
eSomeState_D = 4,
/* do not reach 100 */
}
union uSomeState{
enum eSomeState state;
enum eSomeErrorFromOtherModule err;
}
/* functions updated to */
bool doSomthingA( union eSomeState* const state){
Assert(state->state == eSomeState_A);
//do stuff
if (success){
state->state = eSomeState_B;
return true;
}else{
state->err = err;
}
return false;
}
版本 2 [我没有测试它,因为我几乎没有使用 union 但我希望它能工作] 减少了我的工作,将枚举从另一个模块复制到这个模块..但我仍然必须确保(状态枚举)不重叠(错误枚举)..
- 你对上面的代码有什么看法
- 您有什么建议可以进一步改进?
我喜欢将枚举视为常量的集合(列表)。如果我必须存储状态,那么我会引入一种新类型,例如bitset_t 或 state_t.
示例:
typedef int state_t;
enum someStates {};
enum someErrorStates {};
bool doSomething(state_t state) {}
因为有时需要 'combine' 两个状态在一起(例如通过运算符 '|'),这不在任一枚举的集合中。
个人意见。
补充:
基本上,枚举是一个 int(无符号?),您最多可以在一组中存储 INT_MAX 个值。但是如果你想要一个 'bitset',那么你只能使用 32 个不同的值(如果 int 是 32 位)。如果你想拥有更多,那么你必须实现一个bitset,一个单词数组。
示例:
#define word_size sizeof(unsigned int)
#define word_width (word_size * CHAR_BIT) // defined in limits.h
#define word_index(Pos) ((Pos) / word_width)
#define bit_index(Pos) ((Pos) % word_width)
unsigned int bitset[N];
bool isSet(unsigned int bs[N], unsigned int pos)
{
return ((bs[word_index(pos)] >> bit_index(pos)) & 1);
}
void setBit(unsigned int bs[N], unsigned int pos)
{
bs[word_index(pos)] |= (1 << bit_index(pos));
}
void clearBit(unsigned int bs[N], unsigned int pos)
{
bs[word_index(pos)] &= ~(1 << bit_index(pos));
}
void toggleBit(unsigned int bs[N], unsigned int pos)
{
bs[word_index(pos)] ^= (1 << bit_index(pos));
}
然后你可以这样定义你的枚举:
enum someState {
state1 = 1,
state2 = 2
//...
};
setBit(bitset, state2);
isSet(bitset, state2);
// ... and so on
基本上,枚举常量将描述位集中的(位)位置。