[英]scanf() with C++ enums
以下是我们的代码库中的典型情况。
enum ConfigOption { CONFIG_1=1, CONFIG_2=2, CONFIG_3=3 }
ConfigOption cfg1, cfg2;
sscanf(s, "%d", &cfg1);
这是一个内部使用的仿真软件。 没有分发。 易于维护和正确性非常重要。 可移植性和用户界面 - 不是真的。
问题是c ++中的enum
不一定是int
。 因此,我们会收到编译器警告,并且在使用其他编译器或启用优化时可能会出现错误行为。
一种解决方案就是将&cfg
为int*
。 但是,这不会捕获编译器决定在enum
分配int
以外的东西的情况。
所以我提出了以下解决方案:
template<typename T> inline
int& eint(T& enum_var) {
assert(sizeof(T) == sizeof(int));
return (int&)enum_var;
}
现在使用scanf
如下:
sscanf(s, "%d", &eint(cfg1));
我很想听听上述问题的意见和其他(更好的)解决方案。 请记住,其中一个目标是保持代码简单。 这不是“生产质量”的东西,你添加的越多 - 维护就越困难。
如果你有像vs2010这样的现代编译器,你可以指定枚举元素的大小
enum class ConfigOption: unsigned int {CONFIG_1=1, CONFIG_2=2, CONFIG_3=3};
它在C ++ 0x中的新功能
我的解决方案是将枚举强制到最小尺寸。这就是微软在他们的DirectX头文件中为他们的枚举所做的事情(我不得不承认这是一个很好的技巧)。
他们通过添加如下虚拟枚举来强制枚举的大小等于int:
typedef enum
{
fooo = 1,
baar = 2,
___Force32Bit = ~0UL
} MyEnum;
现在枚举总是至少是int的大小。
如果你愿意,你可以把它放在顶部..这个强迫enum的大小很长:
typedef enum
{
fooo = 1,
baar = 2,
___Force64Bit = ~0ULL
} MyEnum;
我知道,这不是一个超级干净的解决方案。 我认为这样的解决方案不存在,并且到目前为止,强制执行最小尺寸对我来说效果很好。 如果你从32位到64位代码,你可能需要调整代码,但通常在这些情况下你必须检查代码的某些部分,所以没有大问题。
顺便说一句 - 对不起C代码,我知道这个问题被标记为C ++,但我是C-guys :-)
为什么不把它作为一个实际的int
读取?
enum ConfigOption { CONFIG_1=1, CONFIG_2=2, CONFIG_3=3 };
ConfigOption cfg1;
int i;
sscanf(s, "%d", &i);
cfg1 = i;
这样你就可以进行更全面的有效性检查(例如测试读取整数是否在你的enum
类型范围内)。
(当然,如果您一直担心检测错误,对于这样的简单解析,您应该使用strtol
或strtoul
而不是sscanf
。)
您可以尝试使用boost::lexical_cast
,或者如果您不使用boost
并且不想在这种情况下开始使用它,您可以自己编写一个简化版本。 举个例子来看看这个SO答案 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.