C 및 C ++에서 다르게 작동하는 열거 형 상수
이유 :
#include <stdio.h>
#include <limits.h>
#include <inttypes.h>
int main() {
enum en_e {
en_e_foo,
en_e_bar = UINT64_MAX,
};
enum en_e e = en_e_foo;
printf("%zu\n", sizeof en_e_foo);
printf("%zu\n", sizeof en_e_bar);
printf("%zu\n", sizeof e);
}
4 8 8
C 및 8 8 8
C ++로 인쇄 합니까 (4 바이트 정수가있는 플랫폼에서)?
나는 UINT64_MAX
할당이 모든 열거 상수를 적어도 64 비트로 강제하지만 en_e_foo
평범한 C에서는 32로 남아 있다는 인상 을 받았다 .
불일치의 근거는 무엇입니까?
C에서 enum
상수는 유형 int
입니다. C ++에서는 열거 형입니다.
enum en_e{
en_e_foo,
en_e_bar=UINT64_MAX,
};
C에서 이것은 제약 조건 위반 이며 진단이 필요합니다 ( 를 UINT64_MAX
초과하면 INT_MAX
아마도 그렇게 할 것입니다). AC 컴파일러는 프로그램을 완전히 거부하거나 경고를 출력 한 다음 동작이 정의되지 않은 실행 파일을 생성 할 수 있습니다. (제한을 위반하는 프로그램이 반드시 정의되지 않은 동작을 갖는 것은 100 % 명확하지 않지만,이 경우 표준은 동작이 무엇인지 말하지 않으므로 여전히 정의되지 않은 동작입니다.)
gcc 6.2는 이에 대해 경고하지 않습니다. clang은 않습니다. 이것은 gcc의 버그입니다. 표준 헤더의 매크로가 사용될 때 일부 진단 메시지를 잘못 금지합니다. 버그 보고서를 찾아 준 Grzegorz Szpetkowski에게 감사드립니다 : https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71613
C ++에서 각 열거 유형에는 정수 유형 (반드시 아님 ) 인 기본 유형 이 있습니다 int
. 이 기본 유형은 모든 상수 값을 나타낼 수 있어야합니다. 이 경우에, 양 en_e_foo
및 en_e_bar
타입 인 en_e
경우에도 넓은 적어도 64 비트이어야 int
좁다.
그 코드는 처음부터 유효한 C가 아닙니다.
C99 및 C11의 섹션 6.7.2.2에 따르면 다음과 같습니다.
제약 :
열거 상수의 값을 정의하는 표현식은
int
. 로 표현할 수있는 값을 갖는 정수 상수 표현식이어야합니다 .
제약 조건 위반이므로 컴파일러 진단은 필수입니다. 5.1.1.3을 참조하십시오.
준수 구현은 동작이 정의되지 않음 또는 구현으로 명시 적으로 지정 되더라도 전처리 번역 단위 또는 번역 단위에 구문 규칙 또는 제약 위반이 포함 된 경우 적어도 하나의 진단 메시지 (구현 정의 방식으로 식별 됨)를 생성해야합니다. 한정된.
에서 C A는 동안, enum
별도의 유형으로 간주되고, 그 자체가 항상 유형이 열거 int
.
C11-6.7.2.2 열거 지정자
3 열거 자 목록의 식별자는 int 유형의 상수로 선언됩니다.
따라서 표시되는 동작은 컴파일러 확장입니다.
값이 너무 클 경우 열거 자 중 하나의 크기 만 확장하는 것이 합리적이라고 말하고 싶습니다.
반면에 C ++에서는 모든 열거 자에 enum
선언 된 형식이 있습니다.
따라서 모든 열거 자의 크기는 동일해야합니다. 따라서 전체 크기 enum
가 확장되어 가장 큰 열거자를 저장합니다.
다른 사람들이 지적했듯이 제약 조건 위반으로 인해 코드 형식이 잘못되었습니다 (C에서).
GCC 버그 # 71613 (2016 년 6 월보고 됨)이 있는데, 이는 일부 유용한 경고가 매크로를 사용하여 음소거되었음을 나타냅니다.
시스템 헤더의 매크로를 사용할 때 유용한 경고가 침묵하는 것 같습니다. 예를 들어 아래 예에서 경고는 두 열거 형 모두에 유용하지만 하나의 경고 만 표시됩니다. 다른 경고에 대해서도 마찬가지 일 수 있습니다.
현재 해결 방법은 매크로 앞에 단항 +
연산자 를 추가하는 것입니다 .
enum en_e {
en_e_foo,
en_e_bar = +UINT64_MAX,
};
which yields compilation error on my machine with GCC 4.9.2:
$ gcc -std=c11 -pedantic-errors -Wall main.c
main.c: In function ‘main’:
main.c:9:20: error: ISO C restricts enumerator values to range of ‘int’ [-Wpedantic]
en_e_bar = +UINT64_MAX
C11 - 6.7.2.2/2
The expression that defines the value of an enumeration constant shall be an integer constant expression that has a value representable as an
int
.
en_e_bar=UINT64_MAX
is a constraint violation and this makes the above code invalid. A diagnostic message should be produce by confirming implementation as stated in the C11 draft:
A conforming implementation shall produce at least one diagnostic message (identified in an implementation-defined manner) if a preprocessing translation unit or translation unit contains a violation of any syntax rule or constraint, [...]
It seems that GCC has some bug and it failed to produce the diagnostic message. (Bug is pointed in the answer by Grzegorz Szpetkowski
I took a look at the standards and my program appears to be a constraint violation in C because of 6.7.2.2p2:
Constraints: The expression that defines the value of an enumeration constant shall be an integer constant expression that has a value representable as an int.
and defined in C++ because of 7.2.5:
If the underlying type is not fixed, the type of each enumerator is the type of its initializing value: — If an initializer is specified for an enumerator, the initializing value has the same type as the expression and the constant-expression shall be an integral constant expression (5.19). — If no initializer is specified for the first enumerator, the initializing value has an unspecified integral type. — Otherwise the type of the initializing value is the same as the type of the initializing value of the preceding enumerator unless the incremented value is not representable in that type, in which case the type is an unspecified integral type sufficient to contain the incremented value. If no such type exists, the program is ill-formed.
참고URL : https://stackoverflow.com/questions/41836658/enum-constants-behaving-differently-in-c-and-c
'programing tip' 카테고리의 다른 글
Firefox에서 파일 다운로드 대화 상자에 액세스 (0) | 2020.10.05 |
---|---|
Python 2.4에서 파일을 안전하게 열고 닫는 방법 (0) | 2020.10.05 |
React Native : View onPress가 작동하지 않습니다. (0) | 2020.10.05 |
JavaScript에서 다른 문자열의 모든 발생 색인을 찾는 방법은 무엇입니까? (0) | 2020.10.05 |
부모 상태 변경 후 React 자식 구성 요소가 업데이트되지 않음 (0) | 2020.10.05 |