C ++ 열거 형은 서명되었거나 서명되지 않았습니까?
C ++ 열거 형은 서명되었거나 서명되지 않았습니까? 그리고 확장에 의해 입력이 <= 최대 값인지 확인하고> = 최소 값을 제외하는 것이 안전합니까 (0에서 시작하고 1 씩 증가한다고 가정)?
특정 표현에 의존해서는 안됩니다. 다음 링크를 읽으십시오 . 또한 표준은 어떤 값이 int 또는 unsigned int에 맞지 않는 한 int보다 클 수 없다는 점을 제외하고는 enum의 기본 유형으로 사용되는 정수 유형이 구현 정의되어 있다고 말합니다.
요컨대, 서명되거나 서명되지 않은 열거 형에 의존 할 수 없습니다.
소스로 가자. 다음은 C ++ 03 표준 (ISO / IEC 14882 : 2003) 문서가 7.2-5 (열거 선언)에서 말하는 내용입니다.
열거 형의 기본 형식은 열거 형에 정의 된 모든 열거 자 값을 나타낼 수있는 정수 형식입니다. 열거 자의 값이 int 또는 unsigned int에 맞지 않는 한 기본 형식이 int보다 클 수 없다는 점을 제외하고 열거 형의 기본 형식으로 사용되는 정수 형식은 구현에 따라 정의됩니다.
간단히 말해, 컴파일러는 선택해야합니다 (분명히 일부 열거 값에 대해 음수가 있으면 서명됩니다).
서명 여부에 의존해서는 안됩니다. 명시 적으로 서명하거나 서명하지 않으려면 다음을 사용할 수 있습니다.
enum X : signed int { ... }; // signed enum
enum Y : unsigned int { ... }; // unsigned enum
서명 여부에 의존해서는 안됩니다. 표준에 따르면 enum의 기본 유형으로 사용되는 정수 유형이 구현에 의해 정의됩니다. 그러나 대부분의 구현에서는 부호있는 정수입니다.
C ++ 0x에서는 강력한 형식의 열거 가 추가되어 다음과 같은 열거 형의 형식을 지정할 수 있습니다.
enum X : signed int { ... }; // signed enum
enum Y : unsigned int { ... }; // unsigned enum
하지만 지금도 열거 형을 다음과 같은 변수 또는 매개 변수 유형으로 사용하여 몇 가지 간단한 유효성 검사를 수행 할 수 있습니다.
enum Fruit { Apple, Banana };
enum Fruit fruitVariable = Banana; // Okay, Banana is a member of the Fruit enum
fruitVariable = 1; // Error, 1 is not a member of enum Fruit
// even though it has the same value as banana.
컴파일러는 열거 형의 서명 여부를 결정할 수 있습니다.
열거 형의 유효성을 검사하는 또 다른 방법은 열거 형 자체를 변수 유형으로 사용하는 것입니다. 예를 들면 :
enum Fruit
{
Apple = 0,
Banana,
Pineapple,
Orange,
Kumquat
};
enum Fruit fruitVariable = Banana; // Okay, Banana is a member of the Fruit enum
fruitVariable = 1; // Error, 1 is not a member of enum Fruit even though it has the same value as banana.
일부 오래된 답변도 44 개의 찬성표를 받았지만 모든 답변에 동의하지 않는 경향이 있습니다. 요컨대, 우리가 underlying type
열거 형 에 대해 신경 써야한다고 생각하지 않습니다 .
우선, C ++ 03 Enum 유형은 기호 개념이없는 고유 한 유형입니다. C ++ 03 표준부터dcl.enum
7.2 Enumeration declarations
5 Each enumeration defines a type that is different from all other types....
따라서 열거 형 유형의 부호에 대해 이야기 할 때, 예를 들어 <
연산자를 사용하여 두 개의 열거 형 피연산자를 비교할 때 실제로 열거 형 유형을 정수 유형으로 암시 적으로 변환하는 것에 대해 이야기하고 있습니다. 중요한 것은이 통합 유형의 표시입니다 . enum을 정수 유형으로 변환 할 때 다음 문이 적용됩니다.
9 The value of an enumerator or an object of an enumeration type is converted to an integer by integral promotion (4.5).
그리고 분명히 기본 유형의 열거 형은 Integral Promotion과 관련이 없습니다. 표준은 다음과 같이 통합 프로모션을 정의하기 때문에 :
4.5 Integral promotions conv.prom
.. An rvalue of an enumeration type (7.2) can be converted to an rvalue of the first of the following types that can represent all the values of the enumeration
(i.e. the values in the range bmin to bmax as described in 7.2: int, unsigned int, long, or unsigned long.
그래서, 열거 형이되고 있는지 signed int
또는 unsigned int
여부에 따라 signed int
정의 된 열거, 열거 아닌 기본 타입의 모든 값을 포함 할 수 있습니다.
내 관련 질문을 참조하십시오 Sign of C ++ Enum Type Incorrect After Converting to Integral Type
앞으로 C ++ 0x에서는 강력한 형식의 열거 를 사용할 수 있으며 몇 가지 이점 (예 : 형식 안전성, 명시 적 기본 형식 또는 명시 적 범위 지정)이 있습니다. 그것으로 당신은 유형의 표시를 더 잘 확신 할 수 있습니다.
다른 사람들이 이미 서명 된 / 서명되지 않은 것에 대해 말한 것 외에도 열거 형 유형의 범위에 대해 표준이 말하는 내용은 다음과 같습니다.
7.2 (6) : "e (min)가 가장 작은 열거 자이고 e (max)가 가장 큰 열거의 경우 열거의 값은 b (min)에서 b (max) 범위의 기본 유형 값입니다. ), 여기서 b (min) 및 b (max)는 각각 e (min) 및 e (max)를 저장할 수있는 가장 작은 비트 필드의 최소값과 최대 값입니다. 값이 정의되지 않은 열거 형을 정의 할 수 있습니다. 열거 자에 의해. "
예를 들면 :
enum { A = 1, B = 4};
defines an enumerated type where e(min) is 1 and e(max) is 4. If the underlying type is signed int, then the smallest required bitfield has 4 bits, and if ints in your implementation are two's complement then the valid range of the enum is -8 to 7. If the underlying type is unsigned, then it has 3 bits and the range is 0 to 7. Check your compiler documentation if you care (for example if you want to cast integral values other than enumerators to the enumerated type, then you need to know whether the value is in the range of the enumeration or not - if not the resulting enum value is unspecified).
Whether those values are valid input to your function may be a different issue from whether they are valid values of the enumerated type. Your checking code is probably worried about the former rather than the latter, and so in this example should at least be checking >=A and <=B.
Check it with std::is_signed<std::underlying_type
+ scoped enums default to int
https://en.cppreference.com/w/cpp/language/enum implies:
main.cpp
#include <cassert>
#include <iostream>
#include <type_traits>
enum Unscoped {};
enum class ScopedDefault {};
enum class ScopedExplicit : long {};
int main() {
// Implementation defined, let's find out.
std::cout << std::is_signed<std::underlying_type<Unscoped>>() << std::endl;
// Guaranteed. Scoped defaults to int.
assert((std::is_same<std::underlying_type<ScopedDefault>::type, int>()));
// Guaranteed. We set it ourselves.
assert((std::is_same<std::underlying_type<ScopedExplicit>::type, long>()));
}
Compile and run:
g++ -std=c++17 -Wall -Wextra -pedantic-errors -o main main.cpp
./main
Output:
0
Tested on Ubuntu 16.04, GCC 6.4.0.
참고URL : https://stackoverflow.com/questions/159034/are-c-enums-signed-or-unsigned
'program tip' 카테고리의 다른 글
파이썬에서 "예기치 않은 들여 쓰기"로 무엇을해야합니까? (0) | 2020.08.13 |
---|---|
Rails에서 기본값을 설정하는 방법은 무엇입니까? (0) | 2020.08.13 |
UNIX 시대를 Date 객체로 변환 (0) | 2020.08.13 |
이미 업로드 된 Lambda 함수 다운로드 (0) | 2020.08.13 |
Google Maps API v3 : 마커 아이콘을 어떻게 동적으로 변경하나요? (0) | 2020.08.13 |