2014-09-19 1 views
1

하십시오 포함 true 또는 false 모든 사이즈의 유형 bool의 비트 필드에 저장되는 값 경우int 타입의 비트 필드를 사용해야합니까? 드래프트 C++ 표준 (N3337)에서

9.6 비트 필드

4- (1 bit bit-field), 원래의 bool 값과 비트 필드의 값은 같아야한다. 열거 자의 값이 동일한 열거 유형의 비트 필드에 저장되고 비트 필드의 비트 수가 해당 열거 유형 (7.2)의 모든 값을 보유 할만큼 충분히 큰 경우 원래 열거 자 값과 비트 필드의 값은 같음을 비교해야한다.

표준은 다른 유형의 비트 필드에 대한 이러한 동작에 대해 비공식적입니다. g ++ (4.7.3)는 비트 필드의 다른 유형을 다루는 방법을 이해하기 위해, 나는 다음과 같은 테스트 프로그램을 사용 :

#include <iostream> 

enum TestEnum 
{ 
    V1 = 0, 
    V2 
}; 

struct Foo 
{ 
    bool   d1:1; 
    TestEnum  d2:1; 
    int   d3:1; 
    unsigned int d4:1; 
}; 

int main() 
{ 
    Foo foo; 
    foo.d1 = true; 
    foo.d2 = V2; 
    foo.d3 = 1; 
    foo.d4 = 1; 

    std::cout << std::boolalpha; 

    std::cout << "d1: " << foo.d1 << std::endl; 
    std::cout << "d2: " << foo.d2 << std::endl; 
    std::cout << "d3: " << foo.d3 << std::endl; 
    std::cout << "d4: " << foo.d4 << std::endl; 
    std::cout << std::endl; 

    std::cout << (foo.d1 == true) << std::endl; 
    std::cout << (foo.d2 == V2) << std::endl; 
    std::cout << (foo.d3 == 1) << std::endl; 
    std::cout << (foo.d4 == 1) << std::endl; 

    return 0; 
} 

출력 :

 
d1: true 
d2: 1 
d3: -1 
d4: 1 

true 
true 
false 
true 

I가의 선으로 놀랐습니다 Foo::d3에 해당하는 출력. 출력은 ideone.com과 같습니다.

표준은 int 유형의 비트 필드 비교에 대한 약속이 없으므로 g ++은 표준을 위반하지 않는 것으로 보입니다. 그것은 내 질문에 나를 데려다 준다.

int의 비트 필드를 사용하는 것이 좋지 않습니까? 낙심해야할까요?

+3

글쎄, 나는 적어도 비트 필드에'unsigned' 타입을 사용 하겠지만,'signed' 타입은 의미론을 이해하지 못할 것입니다. –

답변

3

그렇습니다. int의 비트 필드는 서명이 구현 정의되어 있기 때문에 좋지 않습니다. 대신 signed int 또는 unsigned int을 사용하십시오. 비 비트 필드 선언에 대한

는 유형 이름 intsigned int (또는 int signed, 또는 signed) 정확히 동일합니다. short, longlong long에 대해서도 동일한 패턴이 적용됩니다. 채워지지 않은 유형 이름은 이며으로 서명되고 해당 서명되지 않은 유형의 이름을 지정하려면 unsigned 키워드를 추가해야합니다.

비트 필드는 역사적인 이유로 특별한 경우입니다. int 유형으로 정의 된 비트 필드는 signed int과 동일한 선언에 대해 또는 unsigned int과 동일한 선언으로 동일하게 입니다. 선택은 구현에 따라 결정됩니다 (즉, 프로그래머가 아닌 컴파일러에 따라 달라집니다). 비트 필드는 intsigned int이 (반드시) 동의어가 아닌 유일한 컨텍스트입니다. char, short, longlong long에도 동일하게 적용됩니다. 는 C++ 11 표준을 인용

는 섹션 9.6 [class.bit]

이것은 구현 - 정의인지 일반 (둘 다 명시 서명하지도 부호) char, short, int, long, 또는 long long 비트 필드 서명 또는 서명 이다.

(나는이에 대한 근거 완전히 확실하지 않다. C의 아주 오래된 버전은 unsigned 키워드를하지 않았고, 부호 비트 필드는 일반적으로 서명 비트 필드보다 더 유용합니다. 그것은 어떤 것을 할 수있다 초기 C 컴파일러는 unsigned 키워드가 도입되기 전에 비트 필드를 구현했습니다. int으로 선언 된 경우에도 기본적으로 비트 필드를 부호없는 상태로 만드는 것은 단순한 문제 였을 수 있습니다. 이전 코드를 손상시키는 것을 피하기위한 다른 이유는 없습니다 .)

대부분의 비트 필드는 부호가없는 것으로되어 있지만 물론 그 정의가 있어야합니다.

부호가있는 비트 필드 (예 : 비 2의 보수 시스템에서 -8에서 +7 또는 -7에서 +7까지의 값을 나타낼 수있는 4 비트 필드)를 원한다면 명시 적으로이를 signed int으로 정의해야합니다. int으로 정의하면 일부 컴파일러에서는 unsigned int으로 처리합니다. 당신이 당신의 비트 필드에 서명 또는 서명 여부를 상관하지 않는 경우

, 당신은 int로 정의 할 수 있습니다 -하지만 당신은 비트 필드를 정의하는 경우에, 당신은 거의 확실 이 서명 여부 관리을하거나 서명되지 않은.

0

intsigned이고, C++ Two's complement에 저장 될 수있다 제 int의 바이트 기호 있도록 사용될 수있다. signed int에 대해 2 비트가있는 경우 1, see it working과 같을 수 있습니다.

+2

@Praetorian 그들은 부호 비트를 명령한다. 따라서 1 비트 부호가있는 필드는별로 의미가 없습니다. – rici

+0

@rici 내가 댓글을 달았을 때 대답은 2의 보수가 항상 사용된다는 의미입니다. 나는 그 부분만을 언급하고 있었다. – Praetorian

0

이것은 완전히 논리적입니다. int은 부호있는 정수형이며 기본 아키텍처가 부호있는 정수를 나타내는 데 2의 보수를 사용하는 경우 (모든 현대 아키텍처 에서처럼) 상위 비트는 부호 비트입니다. 따라서 1 비트 부호있는 정수 비트 필드는 0 또는 -1 값을 취할 수 있습니다. 예를 들어, 3 비트 부호있는 정수 비트 필드는 -43 사이의 값을 가질 수 있습니다.

2의 보수 표현을 이해하는 한 부호가있는 정수 비트 필드에 대한 담요 금지가 필요하지 않습니다.

+1

rici와 Keith Thompson의 답을 살펴보면 플랫폼이 2의 보수 표현 또는 1의 보수 표현을 사용하는지 여부가 문제가되지 않습니다. 문제는 'int'는 비트 필드에서 사용될 때 'signed int'또는 'unsigned int'가 될 수 있다는 것입니다. 유형에 대해 명시 적으로 표현하는 것이 더 합리적입니다. –

+0

@RSahu : 고마워요! 나는 'int'비트 필드가 부호가 있거나 부호가 없다는 것을 알지 못했다. – TonyK

+0

답변을 게시 할 때까지 그 사실을 알지 못했습니다. –

2

unsigned 비트 필드의 크기는 unsigned int 이하 여야합니다. signed 비트 필드는 유효하지만 (적어도 너비가 1보다 큰 경우) 개인적으로는 사용하지 않는 것이 좋습니다. 그러나 서명 된 비트 필드를 사용하려는 경우 명시 적으로 signed으로 표시해야합니다. 이는 정규화되지 않은 int 비트 필드가 부호가 있거나 서명이 없는지 여부에 따라 구현에 의존하기 때문입니다. (이 char 유사하지만, 명시 적으로 규정되지 않은 char* 리터럴의 복잡한 기능없이.) 그 정도에 따라서

, 나는 int 비트 필드는 낙담한다 동의합니다.[주 1] int 비트 필드는 암시 적으로 부호가없는 구현을 알지 못하지만 표준에 의해 확실히 허용되므로 결과적으로 징후에 대해 명시하지 않으면 구현에 따른 예상치 못한 동작이 발생할 수 있습니다. .

표준은 부호있는 정수 표현이 선택적 패딩 비트, 정확히 한 부호 비트 및 값 비트로 구성되도록 지정합니다. 이 표준은 적어도 하나의 값 비트가 있음을 보장하지는 않지만, OP의 예 에서처럼 gcc은 명시 적으로 해석 할 필요가 있다고 생각하지 않습니다. 패딩 비트 (padding bit)가 없어야하며, 값 비트에 해당하는 그러한 표현을 가지지 않는다.

  • 2의 보수, 단일 비트 필드가 1 구성하는 -1

  • 1의 보수로 해석한다 : 어떤 경우에

    허용 단지 세 가지 서명 표현이있다 및 부호 크기. 이 두 경우 모두 1으로 구성된 단일 비트 필드는 트랩 표현이 될 수 있으므로 1 비트 부호있는 비트 필드에서 나타낼 수있는 유일한 숫자는 0입니다.

휴대용 코드는 1 비트 부호있는 비트 필드가 0이 아닌 값을 나타낼 수 있다고 가정 할 수 없기 때문에

, 부호 비트 필드에 관계없이 여부의 적어도 2 비트를 주장하는 합리적인 것 같다 실제로 요구되는지 아닌지에 대한 표준을 해석하십시오.


참고 :이 문자열 리터럴을 명시 적으로 자격이 있다는 사실이 없었다면 사실

  1. , 난 항상 unsigned char를 지정하는 것을 선호합니다. 하지만 그 시점에서 기록을 되돌릴 방법이 없습니다.)