C语言 为什么对 C 枚举定义中的值使用 Bitwise-Shift 运算符?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3999922/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why use the Bitwise-Shift operator for values in a C enum definition?
提问by Dave Gallagher
Apple sometimes uses the Bitwise-Shift operator in their enumdefinitions. For example, in the CGDirectDisplay.hfile which is part of Core Graphics:
Apple 有时会在其枚举定义中使用 Bitwise-Shift 运算符。例如,在作为Core Graphics 一部分的CGDirectDisplay.h文件中:
enum {
kCGDisplayBeginConfigurationFlag = (1 << 0),
kCGDisplayMovedFlag = (1 << 1),
kCGDisplaySetMainFlag = (1 << 2),
kCGDisplaySetModeFlag = (1 << 3),
kCGDisplayAddFlag = (1 << 4),
kCGDisplayRemoveFlag = (1 << 5),
kCGDisplayEnabledFlag = (1 << 8),
kCGDisplayDisabledFlag = (1 << 9),
kCGDisplayMirrorFlag = (1 << 10),
kCGDisplayUnMirrorFlag = (1 << 11),
kCGDisplayDesktopShapeChangedFlag = (1 << 12)
};
typedef uint32_t CGDisplayChangeSummaryFlags;
Why not simply use incrementing int's like in a "normal" enum?
为什么不简单地在“普通”枚举中使用递增int?
回答by pmg
Maybe writing the values in hexadecimal (or binary) helps :-)
也许以十六进制(或二进制)写入值有帮助:-)
enum {
kCGDisplayBeginConfigurationFlag = (1 << 0), /* 0b0000000000000001 */
kCGDisplayMovedFlag = (1 << 1), /* 0b0000000000000010 */
kCGDisplaySetMainFlag = (1 << 2), /* 0b0000000000000100 */
kCGDisplaySetModeFlag = (1 << 3), /* 0b0000000000001000 */
kCGDisplayAddFlag = (1 << 4), /* 0b0000000000010000 */
kCGDisplayRemoveFlag = (1 << 5), /* 0b0000000000100000 */
kCGDisplayEnabledFlag = (1 << 8), /* 0b0000000100000000 */
kCGDisplayDisabledFlag = (1 << 9), /* 0b0000001000000000 */
kCGDisplayMirrorFlag = (1 << 10),/* 0b0000010000000000 */
kCGDisplayUnMirrorFlag = (1 << 11),/* 0b0000100000000000 */
kCGDisplayDesktopShapeChangedFlag = (1 << 12) /* 0b0001000000000000 */
};
Now you can add them (or "or" them) and get different values
现在您可以添加它们(或“或”它们)并获得不同的值
kCGDisplayAddFlag | kCGDisplayDisabledFlag /* 0b0000001000010000 */
回答by sepp2k
This way you can add multiple flags together to create a "set" of flags and can then use &to find out whether any given flag is in such a set.
通过这种方式,您可以将多个标志添加在一起以创建一组“标志”,然后可以&用来找出任何给定的标志是否在这样的集合中。
You couldn't do that if it simply used incrementing numbers.
如果它只是使用递增数字,则无法做到这一点。
Example:
例子:
int flags = kCGDisplayMovedFlag | kCGDisplaySetMainFlag; // 6
if(flags & kCGDisplayMovedFlag) {} // true
if(flags & kCGDisplaySetModeFlag) {} // not true
回答by Florian
If you have FlagA=1, FlagB=2 and FlagC=3, FlagA or FlagB would give the same value as FlagC. The shift operator is used to ensure that every combination of flags is unique.
如果您有 FlagA=1、FlagB=2 和 FlagC=3,FlagA 或 FlagB 将给出与 FlagC 相同的值。移位运算符用于确保每个标志组合都是唯一的。
回答by AustinWBryan
New in C# 7 is finally adding binary literals, so you can just write it as this:
C# 7 中的新功能终于添加了二进制文字,所以你可以这样写:
enum MyEnum
{
kCGDisplayBeginConfigurationFlag = 0b0000000000000001;
kCGDisplayMovedFlag = 0b0000000000000010;
kCGDisplaySetMainFlag = 0b0000000000000100;
kCGDisplaySetModeFlag = 0b0000000000001000;
kCGDisplayAddFlag = 0b0000000000010000;
kCGDisplayRemoveFlag = 0b0000000000100000;
kCGDisplayEnabledFlag = 0b0000000001000000;
kCGDisplayDisabledFlag = 0b0000000010000000;
kCGDisplayMirrorFlag = 0b0000000100000000;
kCGDisplayUnMirrorFlag = 0b0000001000000000;
kCGDisplayDesktopShapeChangedFlag = 0b0000010000000000;
};
And if you want to make things even neater, you use this: _which is also new to C# 7, which allows you to put spaces in numbers to make things more readable, like so:
如果你想让事情更整洁,你可以使用这个:_这也是 C# 7 的新功能,它允许你在数字中放置空格以提高可读性,如下所示:
enum MyEnum
{
kCGDisplayBeginConfigurationFlag = 0b_0000_0000_0000_0001;
kCGDisplayMovedFlag = 0b_0000_0000_0000_0010;
kCGDisplaySetMainFlag = 0b_0000_0000_0000_0100;
kCGDisplaySetModeFlag = 0b_0000_0000_0000_1000;
kCGDisplayAddFlag = 0b_0000_0000_0001_0000;
kCGDisplayRemoveFlag = 0b_0000_0000_0010_0000;
kCGDisplayEnabledFlag = 0b_0000_0000_0100_0000;
kCGDisplayDisabledFlag = 0b_0000_0000_1000_0000;
kCGDisplayMirrorFlag = 0b_0000_0001_0000_0000;
kCGDisplayUnMirrorFlag = 0b_0000_0010_0000_0000;
kCGDisplayDesktopShapeChangedFlag = 0b_0000_0100_0000_0000;
};
Makes it so much easier to keep track of the numbers.
使跟踪数字变得如此容易。
回答by Vladimir
This will allow for a variable to easily combine multiple flags:
这将允许变量轻松组合多个标志:
unit32_t multFlag = kCGDisplayRemoveFlag | kCGDisplayMirrorFlag | kCGDisplaySetMainFlag'
回答by Jayhello
Let's me give you a more practice example. In c++ when you want to open a file (Open for output, and in binary mode opposed to text mode), you can do it by:
让我给你一个更实际的例子。在 C++ 中,当你想打开一个文件(打开输出,以二进制模式与文本模式相反)时,你可以这样做:
const char *filename = "/home/xy/test.bin";
fstream output(filename, ios::out | ios::binary);
You can see, ios::out | ios::binarycan set two mode(Open for output, and in binary mode).
可以看到,ios::out | ios::binary可以设置两种模式(打开输出,和二进制模式)。
How does this work ? It's by enum(bitwise-shift values):
这是如何运作的 ?它是通过枚举(按位移位值):
enum _Ios_Openmode
{
_S_app = 1L << 0,
_S_ate = 1L << 1,
_S_bin = 1L << 2, /* 0b0000000000000100 */
_S_in = 1L << 3,
_S_out = 1L << 4, /* 0b0000000000010000 */
_S_trunc = 1L << 5
//.....
};
/// Perform input and output in binary mode (as opposed to text mode).
static const openmode binary = _S_bin;
/// Open for input. Default for @c ifstream and fstream.
static const openmode in = _S_in;
/// Open for output. Default for @c ofstream and fstream.
static const openmode out = _S_out;
If you use value increment by 1 in enum _Ios_Openmode, you have to set(ios::out)and set(ios::binary)do two times. It may not so convenient to check and set value by one time.
如果您在使用值递增1 enum _Ios_Openmode,你要set(ios::out)和set(ios::binary)做两次。一次检查和设置值可能不太方便。
回答by N 1.1
.. because 1<<7looks more concise and easier to read than 01000000. Doesn't it?
.. 因为1<<7看起来比..更简洁,更容易阅读01000000。不是吗?
回答by richard
using #define is more understandable. but enum could group these value togater.
使用#define 更容易理解。但枚举可以将这些值分组。

