Programming

비트 필드에 값을 할당해도 동일한 값이 반환되지 않는 이유는 무엇입니까?

procodes 2020. 8. 26. 19:33
반응형

비트 필드에 값을 할당해도 동일한 값이 반환되지 않는 이유는 무엇입니까?


이 Quora 게시물 에서 아래 코드를 보았습니다 .

#include <stdio.h>

struct mystruct { int enabled:1; };
int main()
{
  struct mystruct s;
  s.enabled = 1;
  if(s.enabled == 1)
    printf("Is enabled\n"); // --> we think this to be printed
  else
    printf("Is disabled !!\n");
}

C 및 C ++ 모두에서 코드 출력이 예상치 못한 것입니다 .

비활성화되었습니다 !!

그 게시물에 "사인 비트"관련 설명이 나와 있지만, 어떻게 우리가 무언가를 설정하고 그대로 반영하지 않는지 이해할 수 없습니다.

누군가 더 자세한 설명을 할 수 있습니까?


참고 : 비트 필드를 설명하는 표준이 약간 다르기 때문에 태그가 모두 필요합니다. C 사양C ++ 사양에 대한 답변을 참조하십시오 .


비트 필드는 표준에 의해 엄청나게 잘못 정의되어 있습니다. 이 코드가 주어지면 struct mystruct {int enabled:1;};우리 수 없습니다 .

  • 이것이 차지하는 공간의 양-패딩 비트 / 바이트가 있고 메모리에있는 위치.
  • 비트가 메모리에있는 위치. 정의되지 않았으며 엔디안에 따라 다릅니다.
  • int:n비트 필드가 부호있는 것으로 간주 되는지 또는 부호없는 것으로 간주 되는지 여부 입니다.

마지막 부분과 관련하여 C17 6.7.2.1/10은 다음과 같이 말합니다.

비트 필드는 지정된 수의 비트 125 로 구성된 부호있는 또는 부호없는 정수 유형을 갖는 것으로 해석됩니다.

위 내용을 설명하는 비 규범 적 참고 :

125) 위의 6.7.2에 명시된 바와 같이, 사용 된 실제 유형 지정자가 int이거나으로 정의 된 typedef-name int이면 비트 필드가 부호가 있는지 여부가 구현 정의됩니다.

비트 필드를로 간주 signed int하고 약간의 크기를 만들면 1부호 비트에 대해서만 데이터 공간이 없습니다. 이것이 프로그램이 일부 컴파일러에서 이상한 결과를 제공 할 수있는 이유입니다.

좋은 연습:

  • 어떤 목적으로도 비트 필드를 사용하지 마십시오.
  • int모든 형태의 비트 조작에 서명 된 유형을 사용하지 마십시오 .

나는 이해할 수 없습니다. 어떻게 우리가 무언가를 설정했는데 그것이 그대로 나타나지 않는 것이 가능합니다.

왜 컴파일되고 오류가 발생하는지 묻고 있습니까?

예, 이상적으로는 오류가 발생합니다. 컴파일러의 경고를 사용하면 그렇습니다. GCC에서 -Werror -Wall -pedantic:

main.cpp: In function 'int main()':
main.cpp:7:15: error: overflow in conversion from 'int' to 'signed char:1' 
changes value from '1' to '-1' [-Werror=overflow]
   s.enabled = 1;
           ^

이것이 구현 정의에 맡겨진 이유와 오류에 대한 이유는 캐스트가 필요한 이전 코드를 깨는 것을 의미하는 과거 사용과 더 관련이있을 수 있습니다. 이 표준의 저자는 경고가 우려되는 사람들에게 여유를주기에 충분하다고 생각할 수 있습니다.

규범주의를 도입하기 위해 @Lundin의 "어떤 목적으로도 비트 필드를 사용하지 마십시오 . "라는 진술을 반영하겠습니다 . 처음에 비트 필드가 필요하다고 생각하게 만드는 메모리 레이아웃 세부 사항에 대해 낮은 수준의 구체적인 정보를 얻을 수있는 좋은 이유가 있다면 거의 확실하게 가지고있는 다른 관련 요구 사항이 저사양에 맞설 것입니다.

(TL; DR-합법적으로 "필요한"비트 필드를 사용할 수있을만큼 정교하다면 서비스를 제공 할만큼 충분히 정의되지 않은 것입니다.)


이것은 구현 정의 동작입니다. 나는 당신이 이것을 실행하는 기계가 2를 보완하는 부호있는 정수를 사용 int하고이 경우 if 문의 true 부분을 입력하지 않는 이유를 설명하기 위해 부호있는 정수로 취급한다고 가정하고 있습니다.

struct mystruct { int enabled:1; };

enable1 비트 비트 필드로 선언 합니다. 서명되었으므로 유효한 값은 -10입니다. 필드를 1오버플로하도록 설정하면 해당 비트가 다시 돌아갑니다 -1(정의되지 않은 동작).

부호 비트 필드를 처리 할 때 기본적으로 최대 값은 2^(bits - 1) - 1이다 0이 경우.


2의 보수 시스템에서 가장 왼쪽 비트가 부호 비트라고 생각할 수 있습니다. 따라서 가장 왼쪽 비트가 설정된 부호있는 정수는 음수 값입니다.

If you have a 1-bit signed integer, it has only the sign bit. So assigning 1 to that single bit can only set the sign bit. So, when reading it back, the value is interpreted as negative and so is -1.

The values a 1 bit signed integer can hold is -2^(n-1)= -2^(1-1)= -2^0= -1 and 2^n-1= 2^1-1=0


As per the C++ standard n4713, a very similar code snippet is provided. The type used is BOOL (custom), but it can apply to any type.

12.2.4

4 If the value true or false is stored into a bit-field of type bool of any size (including a one bit bit-field), the original bool value and the value of the bit-field shall compare equal. If the value of an enumerator is stored into a bit-field of the same enumeration type and the number of bits in the bit-field is large enough to hold all the values of that enumeration type (10.2), the original enumerator value and the value of the bit-field shall compare equal. [ Example:

enum BOOL { FALSE=0, TRUE=1 };
struct A {
  BOOL b:1;
};
A a;
void f() {
  a.b = TRUE;
  if (a.b == TRUE)    // yields true
    { /* ... */ }
}

— end example ]


At 1st glance, the bold part appears open for interpretation. However, the correct intent becomes clear when the enum BOOL is derived from the int.

enum BOOL : int { FALSE=0, TRUE=1 }; // ***this line
struct mystruct { BOOL enabled:1; };
int main()
{
  struct mystruct s;
  s.enabled = TRUE;
  if(s.enabled == TRUE)
    printf("Is enabled\n"); // --> we think this to be printed
  else
    printf("Is disabled !!\n");
}

With above code it gives a warning without -Wall -pedantic:

warning: ‘mystruct::enabled’ is too small to hold all values of ‘enum BOOL’ struct mystruct { BOOL enabled:1; };

The output is:

Is disabled !! (when using enum BOOL : int)

If enum BOOL : int is made simple enum BOOL, then the output is as the above standard pasage specifies:

Is enabled (when using enum BOOL)


Hence, it can be concluded, also as few other answers have, that int type is not big enough to store value "1" in just a single bit bit-field.


There is nothing wrong with your understanding of bitfields that I can see. What I see is that you redefined mystruct first as struct mystruct { int enabled:1; } and then as struct mystruct s;. What you should have coded was:

#include <stdio.h>

struct mystruct { int enabled:1; };
int main()
{
    mystruct s; <-- Get rid of "struct" type declaration
    s.enabled = 1;
    if(s.enabled == 1)
        printf("Is enabled\n"); // --> we think this to be printed
    else
        printf("Is disabled !!\n");
}

참고 URL : https://stackoverflow.com/questions/53853540/why-is-assigning-a-value-to-a-bit-field-not-giving-the-same-value-back

반응형