your programing

공용체를 통한 유형 실행은 C99에서 지정되지 않았으며 C11에서 지정 되었습니까?

lovepro 2020. 12. 25. 23:36
반응형

공용체를 통한 유형 실행은 C99에서 지정되지 않았으며 C11에서 지정 되었습니까?


스택 오버플로 질문에 대한 여러 답변 은 플로트에 대한 IEEE 단 정밀도 비트를 얻기union 위해 유형 punning에 대한 구조 사용을 제안합니다 (예 : a의 비트를 a float로 변환 uint32_t).

union {
    float f;
    uint32_t u;
} un;
un.f = your_float;
uint32_t target = un.u;

그러나 uint32_t조합원 의 가치 는 C99 표준 (최소한 n1124 초안)에 따라 명시되지 않은 것으로 보이며 섹션 6.2.6.1.7은 다음과 같이 명시합니다.

유니온 유형의 개체 멤버에 값이 저장되면 해당 멤버에 해당하지 않지만 다른 멤버에 해당하는 개체 표현의 바이트는 지정되지 않은 값을 사용합니다.

C11 n1570 초안의 적어도 하나의 각주는 이것이 더 이상 사실이 아님을 암시하는 것 같습니다 (6.5.2.3의 각주 95 참조).

공용체 개체의 내용을 읽는 데 사용 된 멤버가 개체에 값을 저장하는 데 마지막으로 사용 된 멤버와 동일하지 않은 경우 값의 개체 표현 중 적절한 부분은 다음과 같이 새 형식의 개체 표현으로 재 해석됩니다. 6.2.6에 설명되어 있습니다 ( "유형 제거"라고도하는 프로세스). 이것은 트랩 표현 일 수 있습니다.

그러나 섹션 6.2.6.1.7의 텍스트는 C11 초안과 C99 초안에서 동일합니다.

이 동작은 실제로 C99에서 지정되지 않습니까? C11에 명시되어 있습니까? 대부분의 컴파일러가 이것을 지원하는 것 같지만 표준에 지정되어 있는지 아니면 매우 일반적인 확장인지 아는 것이 좋습니다.


union을 사용한 유형 punning의 동작이 C89에서 C99로 변경되었습니다. C99의 동작은 C11과 동일합니다.

마찬가지로 WUG는 그의 대답에 언급, 형 말장난은 C99 / C11 허용됩니다. 공용체 멤버의 크기가 다른 경우 트랩이 될 수있는 지정되지 않은 값을 읽습니다.

각주는 Clive DW Feather Defect Report # 257 이후 C99에 추가되었습니다 .

마지막으로 C90에서 C99로 변경된 사항 중 하나는 마지막 상점이 다른 상점에있을 때 조합의 한 구성원에 대한 액세스 제한을 제거하는 것입니다. 그 이유는 행동이 값의 표현에 의존한다는 것입니다. 이 점은 종종 오해되기 때문에 표준에서 명확히 할 가치가 있습니다.

[...]

"type punning"에 대한 문제를 해결하려면 6.5.2.3 # 3 : 78a의 "named member"라는 단어에 새 각주 78a를 첨부하십시오. 공용체 개체의 내용에 액세스하는 데 사용 된 구성원이 마지막 구성원과 동일하지 않은 경우 객체에 값을 저장하는 데 사용되는 경우 값의 객체 표현 중 적절한 부분은 6.2.6에 설명 된대로 새로운 유형의 객체 표현으로 재 해석됩니다 ( "유형 punning"이라고도 함). 이것은 트랩 표현 일 수 있습니다.

Clive DW Feather의 문구는 C Committee for Defect Report # 283 의 답변에서 Technical Corrigendum에 채택되었습니다 .


원래의 C99 사양에서는이를 지정하지 않았습니다.

C99 (TR2, 제 생각에)에 대한 기술적 정정표 중 하나는이 감독을 수정하기 위해 각주 82를 추가했습니다.

공용체 개체의 내용에 액세스하는 데 사용 된 멤버가 개체에 값을 저장하는 데 마지막으로 사용 된 멤버와 같지 않은 경우 값의 개체 표현 중 적절한 부분은 다음과 같이 새 형식의 개체 표현으로 재 해석됩니다. 6.2.6에 설명되어 있습니다 ( "유형 제거"라고도하는 프로세스). 이것은 트랩 표현 일 수 있습니다.

해당 각주는 C11 표준 (C11의 각주 95)에 유지됩니다.


이것은 항상 "iffy"였습니다. 다른 사람들이 지적했듯이 Technical Corregendum을 통해 C99에 각주가 추가되었습니다. 다음과 같이 읽습니다.

공용체 개체의 내용에 액세스하는 데 사용 된 멤버가 개체에 값을 저장하는 데 마지막으로 사용 된 멤버와 같지 않은 경우 값의 개체 표현 중 적절한 부분은 다음과 같이 새 형식의 개체 표현으로 재 해석됩니다. 6.2.6에 설명되어 있습니다 ( "유형 제거"라고도하는 프로세스). 이것은 트랩 표현 일 수 있습니다.

그러나 각주는 서문에 비표준으로 지정됩니다.

부록 D와 F는이 표준의 규범적인 부분을 구성합니다. 부록 A, B, C, E, G, H, I, J, 참고 문헌 및 색인은 정보 용입니다. ISO / IEC 지침의 Part 3에 따라이 서문, 소개, 참고, 각주 및 예제도 정보 제공 용 입니다.

즉, 각주는 행동을 금지 할 수 없습니다. 기존 텍스트 만 명확히해야합니다. 인기가없는 의견이지만 위에 인용 된 각주는 실제로 이와 관련하여 실패합니다. 규범적인 텍스트에는 그러한 행동이 금지되어 있습니다. 실제로 6.7.2.1과 같은 부분이 있습니다.

... 멤버 중 최대 하나의 값은 언제든지 공용체 개체에 저장할 수 있습니다.

6.5.2.3과 함께 ( "."연산자를 사용하여 유니온 멤버에 액세스하는 경우) :

값은 명명 된 멤버의 값입니다.

즉, 한 멤버의 값만 저장할 수있는 경우 다른 멤버의 값은 존재하지 않습니다. 이것은 공용체를 통한 유형 punning 이 가능 하지 않아야 함을 강하게 의미 합니다. 멤버 액세스가 존재하지 않는 값을 생성합니다. 동일한 텍스트가 C11 문서에 여전히 존재합니다.

그러나 각주를 추가하는 목적은 유형을 입력 할 수 있도록하는 것이 었습니다. 위원회가 규범 적 텍스트를 포함하지 않는 각주에 대한 규칙을 위반 한 것 같습니다. 각주를 받아들이려면 각주가 규범 적이 지 않다고 말하는 부분을 무시하거나 그렇지 않으면 각주의 결론을 뒷받침하는 방식으로 규범 적 텍스트를 해석하는 방법을 알아 내야합니다. 실패했습니다).

인용하는 섹션 :

유니온 유형의 개체 멤버에 값이 저장되면 해당 멤버에 해당하지 않지만 다른 멤버에 해당하는 개체 표현의 바이트는 지정되지 않은 값을 사용합니다.

...하지만주의 깊게 읽어야합니다. " 그 멤버에 해당하지 않는 객체 표현의 바이트 "는 멤버 의 크기를 초과하는 바이트를 참조하며, 이는 유형 punning에 대한 문제가 아닙니다 (유니온 멤버에 쓰기가 더 큰 구성원의 "추가"부분은 그대로).


그러나 이것은 섹션 6.2.6.1.7에서 몇 가지 사항을 언급하는 C99 표준 (최소한 n1124 초안)을 위반하는 것으로 보입니다. 이 동작은 실제로 C99에서 지정되지 않습니까?

아니, 괜찮아.

유니온 유형의 개체 멤버에 값이 저장되면 해당 멤버에 해당하지 않지만 다른 멤버에 해당하는 개체 표현의 바이트는 지정되지 않은 값을 사용합니다.

이는 크기가 다른 데이터 블록에 적용됩니다. 즉, 다음이있는 경우 :

union u
{
    float f;
    double d;
};

and you assign something to f, it would change the lower 4 bytes of d, but the upper 4 bytes would be in an indeterminate state.

Unions exist primarily for type punning.

ReferenceURL : https://stackoverflow.com/questions/11639947/is-type-punning-through-a-union-unspecified-in-c99-and-has-it-become-specified

반응형