나는 이전에 편하게 노동 조합을 사용했다. 오늘 이 게시물을 읽었을 때 놀랐 으며이 코드를 알게되었습니다.
union ARGB
{
uint32_t colour;
struct componentsTag
{
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
} components;
} pixel;
pixel.colour = 0xff040201; // ARGB::colour is the active member from now on
// somewhere down the line, without any edit to pixel
if(pixel.components.a) // accessing the non-active member ARGB::components
실제로 정의되지 않은 동작입니다. 즉 최근에 작성된 조합 이외의 조합 구성원에서 읽는 것은 정의되지 않은 동작으로 이어집니다. 이것이 노조의 의도 된 사용법이 아닌 경우 무엇입니까? 어떤 사람은 정교하게 설명해 주시겠습니까?
최신 정보:
나는 몇 가지를 명확하게 설명하고 싶었다.
- 질문에 대한 대답은 C와 C ++에서 동일하지 않습니다. 내 무식한 젊은 자아는 그것을 C와 C ++로 태그했습니다.
- C ++ 11의 표준을 꼼꼼히 살펴본 후에는 비활성 조합 멤버에 대한 액세스 / 검사가 정의되지 않음 / 지정되지 않음 / 구현이 정의되었다고 결론을 내릴 수 없었습니다. 내가 찾을 수있는 것은 §9.5 / 1입니다.
표준 레이아웃 공용체에 공통 초기 시퀀스를 공유하는 여러 표준 레이아웃 구조체가 포함되어 있고이 표준 레이아웃 공용체 유형의 오브젝트에 표준 레이아웃 구조체 중 하나가 포함 된 경우 모든 표준의 일반 시퀀스를 검사 할 수 있습니다 표준 레이아웃 구조체 멤버 §9.2 / 19 : 대응하는 멤버가 레이아웃 호환 유형을 가지고 있고 멤버가 비트 필드이거나 둘 다 동일한 너비를 가진 비트 필드가 하나 이상의 초기 시퀀스 인 경우 두 개의 표준 레이아웃 구조체가 공통 초기 시퀀스를 공유합니다. 회원.
- C ( C99 TC3-DR 283 이상)에서는 그렇게하는 것이 합법적입니다 ( Pascal Cuoq 덕분에 ). 그러나 읽은 유형에 대해 읽은 값이 유효하지 않은 경우 ( "트랩 표시"라고 함) 이를 수행하려고 해도 여전히 정의되지 않은 동작이 발생할 수 있습니다. 그렇지 않으면 읽은 값이 구현 정의됩니다.
C89 / 90은 지정되지 않은 행동 (Annex J) 하에서 이것을 호출했으며 K & R의 책은 구현이 정의되었다고 말합니다. K & R에서 인용 :
이는 여러 유형 중 하나를 합법적으로 보유 할 수있는 단일 변수 인 공용체의 목적입니다. 사용법이 일관된 한 [...] : 검색된 유형은 가장 최근에 저장된 유형이어야합니다. 현재 어떤 유형이 공용체에 저장되어 있는지 추적하는 것은 프로그래머의 책임입니다. 어떤 것이 한 유형으로 저장되고 다른 유형으로 추출되면 결과는 구현에 따라 다릅니다.
Stroustrup의 TC ++ PL (강조 광산)에서 추출
노동 조합의 사용은 데이터 [...]의 compatness에 필수적 일 수있다 때로는 "유형 변환에 잘못 ".
무엇보다도,이 질문하지 표준이 허용하는 것에 노동 조합의 목적을 이해하는 의도로 제기되었다 (그 제목은 내가 물어 이후 변경되지 않습니다) 물론, C ++ 표준에 의해 허용되는 예는 코드 재사용에 대한 상속을 사용하지만, 상속을 C ++ 언어 기능으로 도입하려는 의도 나 원래 의도는 아니었다 . 이것이 Andrey의 대답이 계속 받아 들여지는 이유입니다.
scouring C++11's standard I couldn't conclusively say that it calls out accessing/inspecting a non-active union member is undefined [...] All I could find was §9.5/1
...정말? 단락 시작 부분의 주요 요점이 아니라 예외 메모 를 인용하면 다음과 같습니다. "유니온에서는 정적이 아닌 데이터 멤버 중 대부분이 언제든지 활성화 될 수 있습니다. 즉, 최대 하나의 값 비 정적 데이터 멤버는 언제든지 통합에 저장할 수 있습니다. " -p4까지 : "일반적으로 명시 적 소멸자 호출 및 배치 새 연산자를 사용하여 조합의 활성 멤버를 변경해야합니다 "
b, g, r,
및a
인접하지 않을 수 있으며, 따라서 (A)의 레이아웃과 일치하지uint32_t
. 이것은 다른 사람들이 지적한 Endianess 문제에 추가됩니다.