unsigned int of bit-field가 C ++에서 shift 연산 후 signed int가되는 이유는 무엇입니까? [복제]
테스트 코드 :
struct A
{
uint32_t lo : 16;
uint32_t hi : 16;
};
int main()
{
A a{};
a.lo = 0xFFFF;
auto b = a.lo << 16;
cout << b << endl;
return 0;
}
출력은 다음과 같습니다 -65536
, 그리고 유형 b
입니다 int
하지만 uint32_t
.
나는 그것을 발견, uint16_t
그리고 uint8_t
또한 시프트 연산자 후 서명 INT 될 것이며, 비슷한 질문이 있었다 C#
피연산자가 <32 비트 때 결과가 체결 될 것이라는 결론에 도달했다. 피연산자가 32 비트 미만일 때 시프트 연산이 항상 부호있는 정수가되는 이유
그러나의 유형 a.lo
은 명확 uint32_t
하며에서 확인할 수 있습니다 decltype(a.lo)
. 그러면 어떻게 설명 할 수 있습니까?
답변
표준 통합 프로모션의 일부입니다.
[expr.shift]
1 시프트 연산자
<<
및>>
그룹 왼쪽에서 오른쪽피연산자는 정수 또는 범위가 지정되지 않은 열거 유형이어야하며 정수 승격이 수행됩니다. 결과 유형은 승격 된 왼쪽 피연산자의 유형입니다.
[conv.prom]
5 정수 비트 필드 ([class.bit])에 대한 prvalue 는 비트 필드의 모든 값을 나타낼 수있는
int
경우 유형의 prvalue로 변환 될 수 있습니다int
. 그렇지 않으면 비트 필드의 모든 값을 나타낼 수있는unsigned int
경우 로 변환 될 수 있습니다unsigned int
. 비트 필드가 아직 더 크면 적분 승격이 적용되지 않습니다. 비트 필드에 열거 된 유형이있는 경우 승격 목적으로 해당 유형의 다른 값으로 처리됩니다.
왼쪽 피연산자 (비트 필드)의 승격은를 생성 int
하므로 이것이 전체 시프트 표현식의 유형입니다. 따라서 b
입니다 int
너무 자리 표시 자 형태 추론에 의해.