c++ enum枚举常量能够存储的值的问题

时间:2022-09-03 14:03:57
enum应该是枚举常量类型,其类型的变量只能够存储规定的几种值,但我研究了一下iostream的state发现:

其中是这么定义的(我稍微改了一下,基本功能和作用不变)


enum iostate
{
goodbit = 1L << 0,
failbit     = 1L << 1,
eofbit     = 1L << 2,
badbit    = 1L << 3,
iostate_end = 1L << 15
}


因为iostream的状态可以同时有多个,所以就有setstate函数,其基本功能就是将这个状态存进一个变量中。
可是这个变量的类型也是这个state枚举类型,按道理来说应该是只能存储5种值才对,但是以下这种赋值方式却可行,而去掉了static_cast静态类型转换则提示无法从Int转换到iostate类型:

iostream::iostate test = static_cast<iostream::iostate>((int)iostream::eofbit | (int)iostream::failbit)


而这时候这个test中的值则不只是定义时规定的那几种值了。这是为什么?难道说是动态的计算?

另外:枚举常量的值默认不就是int类型的吗?为什么在定义时要用长整数移位,而且在下面要添加强制类型转换呢(标准库中是这么写的)?

12 个解决方案

#1


首先,enum枚举类型的变量,并不是只能存储定义的那些值。把下边的代码编译运行一下就知道了。
注意其中的类型转换,如果不转换,编译器会报错。
#include<iostream>
using namespace std;

enum MyEnum
{
  one = 1,
  two = 2
};

int main()
{
  MyEnum a = (MyEnum)1;
  MyEnum b = (MyEnum)2;
  MyEnum c = (MyEnum)3;
  cout << a << ' ' << b << ' ' << c << endl;
}

#2


关于长整数移位,很明显这个iostate类型是作为一个位图来使用的。其中定义的5个值,每个值各有一位置1,代表5种不同的状态,而这几种状态有时候会同时出现其中几种,这时就要把对应的几位置1.
(int)iostream::eofbit | (int)iostream::failbit // 同时设置eof和fail对应的两位,表示这两个状态同时存在。
判断的时候这么写:
if ((state & eofbit) != 0) {
  // eof状态存在
} else {
  // eof状态不存在
}

#3


LZ先学习下|运算。

#4


位域

#5


引用 3 楼 ForestDB 的回复:
LZ先学习下|运算。


引用 4 楼 zhao4zhong1 的回复:
位域


额,长整数移位和|运算我知道,而且原理我也知道,只是他为什么要用长整数移位而不是直接用普通整数型移位呢

#6


大家好像有些理解错了,应该是我说的不清楚。我知道他每一位代表一个状态,如00000001是goodbit,00000010是failbit,如果是00000011就是goodbit | failbit,既goodbit和failbit同时存在。
我不清楚的是书上说:enum实际的值是int类型的。
但根据: goodbit = 1L << 0 这计算出来的结果不是长整数型的吗?还会自动转换成int类型吗?
为什么不直接写成 goodbit = 1 << 0

enum为什么不只是可以存储定义的那些值?他的作用不就是一个选择的作用吗?

#7


因为在16位编译开发环境下,普通整型数的范围是-32768~32767
所以为确保有32位可用,使用长整数移位。

#8


整形有32个状态的组合,但长整形可以有64中状态。

#9


引用 8 楼 ForestDB 的回复:
整形有32个状态的组合,但长整形可以有64中状态。

纯属胡诌

#10


ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/dv_vclang/html/1f3b58a4-8346-4533-ba6e-df26d76f8dcf.htm
 Collapse AllExpand All      Code: All Code: Multiple Code: Visual Basic Code: C# Code: Visual C++ Code: J# Code: JScript  
Visual Basic
C#
Visual C++
J#
JScript
Visual C++ Language Reference 
C++ Integer Constants 
See Also  Send Feedback 
 

Integer constants are constant data elements that have no fractional parts or exponents. They always begin with a digit. You can specify integer constants in decimal, octal, or hexadecimal form. They can specify signed or unsigned types and long or short types.

Grammar
integer-constant: 
decimal-constant integer-suffixopt

octal-constant integer-suffixopt

hexadecimal-constant integer-suffixopt

'c-char-sequence'

decimal-constant: 
nonzero-digit 

decimal-constant digit

octal-constant: 
0

octal-constant octal-digit

hexadecimal-constant: 
0xhexadecimal-digit

0Xhexadecimal-digit 

hexadecimal-constant hexadecimal-digit

nonzero-digit: one of 
1 2 3 4 5 6 7 8 9

octal-digit: one of 
0 1 2 3 4 5 6 7

hexadecimal-digit: one of 
0 1 2 3 4 5 6 7 8 9 

a b c d e f 

A B C D E F

integer-suffix: 
unsigned-suffix long-suffixopt

long-suffix unsigned-suffixopt

unsigned-suffix: one of 
u U

long-suffix: one of 
l L

64-bit integer-suffix: 
i64 LL ll

To specify integer constants using octal or hexadecimal notation, use a prefix that denotes the base. To specify an integer constant of a given integral type, use a suffix that denotes the type.

To specify a decimal constant, begin the specification with a nonzero digit. For example:

  Copy Code 
int i = 157;   // Decimal constant
int j = 0198;  // Not a decimal number; erroneous octal constant
int k = 0365;  // Leading zero specifies octal constant, not decimal
 

To specify an octal constant, begin the specification with 0, followed by a sequence of digits in the range 0 through 7. The digits 8 and 9 are errors in specifying an octal constant. For example:

  Copy Code 
int i = 0377;   // Octal constant
int j = 0397;   // Error: 9 is not an octal digit
 

To specify a hexadecimal constant, begin the specification with 0x or 0X (the case of the "x" does not matter), followed by a sequence of digits in the range 0 through 9 and a (or A) through f (or F). Hexadecimal digits a (or A) through f (or F) represent values in the range 10 through 15. For example:

  Copy Code 
int i = 0x3fff;   // Hexadecimal constant
int j = 0X3FFF;   // Equal to i
 

To specify an unsigned type, use either the u or U suffix. To specify a long type, use either the l or L suffix. For example:

  Copy Code 
unsigned uVal = 328u;             // Unsigned value
long lVal = 0x7FFFFFL;            // Long value specified 
                                  //  as hex constant
unsigned long ulVal = 0776745ul;  // Unsigned long value
 

To specify a 64-bit integral type, use the LL, ll or i64 suffix. For example,

  Copy Code 
// 64bitsuffix.cpp
#include <stdio.h>
enum MyEnum {
   IntType,
   Int64Type
};

MyEnum f1(int) {
   printf("in f1(int)\n");
   return IntType;
}

MyEnum f1(__int64) {
   printf_s("in f1(__int64)\n");
   return Int64Type;
}

int main() {
   MyEnum t1 = f1(0x1234), t2 = f1(0x1234i64);
}
 

Output
  
in f1(int)
in f1(__int64)
 

See Also
Concepts
Literals (C++)
Send feedback on this topic to Microsoft.

#11


不管是多少位的编译开发环境,用长整型总有可能有更多位的状态,仅此而已。
16位下,int是16位,那么long就有32位,状态更多。

#12


谢谢大家了!小弟明白了!!

#1


首先,enum枚举类型的变量,并不是只能存储定义的那些值。把下边的代码编译运行一下就知道了。
注意其中的类型转换,如果不转换,编译器会报错。
#include<iostream>
using namespace std;

enum MyEnum
{
  one = 1,
  two = 2
};

int main()
{
  MyEnum a = (MyEnum)1;
  MyEnum b = (MyEnum)2;
  MyEnum c = (MyEnum)3;
  cout << a << ' ' << b << ' ' << c << endl;
}

#2


关于长整数移位,很明显这个iostate类型是作为一个位图来使用的。其中定义的5个值,每个值各有一位置1,代表5种不同的状态,而这几种状态有时候会同时出现其中几种,这时就要把对应的几位置1.
(int)iostream::eofbit | (int)iostream::failbit // 同时设置eof和fail对应的两位,表示这两个状态同时存在。
判断的时候这么写:
if ((state & eofbit) != 0) {
  // eof状态存在
} else {
  // eof状态不存在
}

#3


LZ先学习下|运算。

#4


位域

#5


引用 3 楼 ForestDB 的回复:
LZ先学习下|运算。


引用 4 楼 zhao4zhong1 的回复:
位域


额,长整数移位和|运算我知道,而且原理我也知道,只是他为什么要用长整数移位而不是直接用普通整数型移位呢

#6


大家好像有些理解错了,应该是我说的不清楚。我知道他每一位代表一个状态,如00000001是goodbit,00000010是failbit,如果是00000011就是goodbit | failbit,既goodbit和failbit同时存在。
我不清楚的是书上说:enum实际的值是int类型的。
但根据: goodbit = 1L << 0 这计算出来的结果不是长整数型的吗?还会自动转换成int类型吗?
为什么不直接写成 goodbit = 1 << 0

enum为什么不只是可以存储定义的那些值?他的作用不就是一个选择的作用吗?

#7


因为在16位编译开发环境下,普通整型数的范围是-32768~32767
所以为确保有32位可用,使用长整数移位。

#8


整形有32个状态的组合,但长整形可以有64中状态。

#9


引用 8 楼 ForestDB 的回复:
整形有32个状态的组合,但长整形可以有64中状态。

纯属胡诌

#10


ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/dv_vclang/html/1f3b58a4-8346-4533-ba6e-df26d76f8dcf.htm
 Collapse AllExpand All      Code: All Code: Multiple Code: Visual Basic Code: C# Code: Visual C++ Code: J# Code: JScript  
Visual Basic
C#
Visual C++
J#
JScript
Visual C++ Language Reference 
C++ Integer Constants 
See Also  Send Feedback 
 

Integer constants are constant data elements that have no fractional parts or exponents. They always begin with a digit. You can specify integer constants in decimal, octal, or hexadecimal form. They can specify signed or unsigned types and long or short types.

Grammar
integer-constant: 
decimal-constant integer-suffixopt

octal-constant integer-suffixopt

hexadecimal-constant integer-suffixopt

'c-char-sequence'

decimal-constant: 
nonzero-digit 

decimal-constant digit

octal-constant: 
0

octal-constant octal-digit

hexadecimal-constant: 
0xhexadecimal-digit

0Xhexadecimal-digit 

hexadecimal-constant hexadecimal-digit

nonzero-digit: one of 
1 2 3 4 5 6 7 8 9

octal-digit: one of 
0 1 2 3 4 5 6 7

hexadecimal-digit: one of 
0 1 2 3 4 5 6 7 8 9 

a b c d e f 

A B C D E F

integer-suffix: 
unsigned-suffix long-suffixopt

long-suffix unsigned-suffixopt

unsigned-suffix: one of 
u U

long-suffix: one of 
l L

64-bit integer-suffix: 
i64 LL ll

To specify integer constants using octal or hexadecimal notation, use a prefix that denotes the base. To specify an integer constant of a given integral type, use a suffix that denotes the type.

To specify a decimal constant, begin the specification with a nonzero digit. For example:

  Copy Code 
int i = 157;   // Decimal constant
int j = 0198;  // Not a decimal number; erroneous octal constant
int k = 0365;  // Leading zero specifies octal constant, not decimal
 

To specify an octal constant, begin the specification with 0, followed by a sequence of digits in the range 0 through 7. The digits 8 and 9 are errors in specifying an octal constant. For example:

  Copy Code 
int i = 0377;   // Octal constant
int j = 0397;   // Error: 9 is not an octal digit
 

To specify a hexadecimal constant, begin the specification with 0x or 0X (the case of the "x" does not matter), followed by a sequence of digits in the range 0 through 9 and a (or A) through f (or F). Hexadecimal digits a (or A) through f (or F) represent values in the range 10 through 15. For example:

  Copy Code 
int i = 0x3fff;   // Hexadecimal constant
int j = 0X3FFF;   // Equal to i
 

To specify an unsigned type, use either the u or U suffix. To specify a long type, use either the l or L suffix. For example:

  Copy Code 
unsigned uVal = 328u;             // Unsigned value
long lVal = 0x7FFFFFL;            // Long value specified 
                                  //  as hex constant
unsigned long ulVal = 0776745ul;  // Unsigned long value
 

To specify a 64-bit integral type, use the LL, ll or i64 suffix. For example,

  Copy Code 
// 64bitsuffix.cpp
#include <stdio.h>
enum MyEnum {
   IntType,
   Int64Type
};

MyEnum f1(int) {
   printf("in f1(int)\n");
   return IntType;
}

MyEnum f1(__int64) {
   printf_s("in f1(__int64)\n");
   return Int64Type;
}

int main() {
   MyEnum t1 = f1(0x1234), t2 = f1(0x1234i64);
}
 

Output
  
in f1(int)
in f1(__int64)
 

See Also
Concepts
Literals (C++)
Send feedback on this topic to Microsoft.

#11


不管是多少位的编译开发环境,用长整型总有可能有更多位的状态,仅此而已。
16位下,int是16位,那么long就有32位,状态更多。

#12


谢谢大家了!小弟明白了!!