C99에서 유니온을 통한 형식연결이 불특정화 되어 있으며, C11에 명시되어 있는가?
스택 오버플로 질문에 대한 여러 가지 대답 플로트의 IEEE 단일 정밀 비트를 얻으려면 다음 항목을 사용하십시오.union
구조(예: 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에 명시되었는가?나는 대부분의 컴파일러들이 이것을 지지하는 것 같다는 것을 알지만, 그것이 표준에 명시되어 있는지 아니면 단지 매우 일반적인 연장선상에 불과한지 알면 좋을 것이다.
유니온과 함께 펀칭하는 타입의 동작은 C89에서 C99로 바뀌었다.C99의 동작은 C11과 같다.
Wug가 답변에서 언급한 바와 같이 C99 / C11에서는 타이프 펀칭이 허용된다.조합원 규모가 다를 때 함정이 될 수 있는 불특정 값을 읽는다.
이 각주는 C99년 클라이브 D.W. 깃털 결함 보고서 #257 이후 추가되었다.
마지막으로, C90에서 C99로 바뀐 것 중 하나는 마지막 가게가 다른 가게일 때 조합원 한 명에게 접근하는 것에 대한 제한을 없애는 것이었다.근거는 그 행동이 그 값들의 표현에 달려있다는 것이었다.이 점은 종종 오해를 받기 때문에 이 기준서에서 명확히 할 가치가 있을 수 있다.
[...]
"형식 펀닝"에 관한 문제를 해결하기 위해 6.5.2.3#3:78a의 "명칭 회원"이라는 단어에 새로운 각주 78a를 첨부한다. 조합 오브젝트의 내용에 접근하기 위해 사용한 단원이 오브젝트에 값을 저장하기 위해 마지막으로 사용한 단원과 동일하지 않을 경우, 해당 값의 오브젝트 표현 중 적절한 부분을 오브젝트 표현으로 재해석한다.6.2.6("형 펀닝"이라고도 하는 프로세스)에 설명된 바와 같이 새로운 유형의 tion.이것은 함정 표현일 수도 있다.
C 위원회의 결함 보고서 #283의 답변에서 Clive D.W. Feather의 문구는 기술 코리젠덤으로 받아들여졌다.
원래의 C99 규격은 이것을 불특정하게 만들었다.
C99(TR2, I think)에 대한 기술 Corrigenda 중 하나는 이러한 감독을 수정하기 위해 각주 82를 추가했다.
조합 오브젝트의 내용에 접근하는 데 사용된 멤버가 오브젝트에 값을 저장하기 위해 마지막으로 사용한 멤버와 동일하지 않을 경우, 해당 값의 오브젝트 표현 중 적절한 부분은 6.2.6("타입 펀닝"이라고도 하는 프로세스)에서 설명한 새로운 타입의 오브젝트 표현으로 재해석된다.이것은 함정 표현일 수도 있다.
이 각주는 C11 표준에 유지된다(C11의 각주 95).
이것은 항상 "불편한" 것이었다.다른 사람들이 지적했듯이 각주는 기술 코레겐덤을 통해 C99에 추가되었다.다음과 같이 읽는다.
조합 오브젝트의 내용에 접근하는 데 사용된 멤버가 오브젝트에 값을 저장하기 위해 마지막으로 사용한 멤버와 동일하지 않을 경우, 해당 값의 오브젝트 표현 중 적절한 부분은 6.2.6("타입 펀닝"이라고도 하는 프로세스)에서 설명한 새로운 타입의 오브젝트 표현으로 재해석된다.이것은 함정 표현일 수도 있다.
그러나 각주는 서문에서 비표준으로 지정된다.
부속문서 D와 F는 이 표준의 규범적 부분을 형성한다. 부속문서 A, B, C, E, G, H, I, J, 참고 문헌 목록 및 색인은 정보만을 위한 것이다.ISO/IEC 지침의 파트 3에 따라, 이 서문, 도입, 주석, 각주 및 예시 또한 정보만을 위한 것이다.
즉, 각주는 행동을 금지할 수 없으며 기존 텍스트만 명확히 해야 한다.그것은 비인기적인 의견이지만, 위에서 인용한 각주는 실제로 이런 점에서 실패한다 - 규범적인 본문에 금지된 그러한 행동은 없다.실제로 6.7.2.1과 같이 모순되는 부분이 있다.
…회원 중 한 명에 대한 가치는 언제든지 조합 객체에 저장할 수 있다.
6.5.2.3 (". 운영자"와 조합원 접근 관련):
값은 명명된 멤버의 값이다.
즉, 한 멤버의 값만 저장할 수 있다면 다른 멤버의 값은 존재하지 않는다.이것은 조합에 의한 펀칭이 가능해서는 안 된다는 것을 강하게 암시한다; 회원 접속은 존재하지 않는 가치를 산출한다.C11 문서에는 여전히 동일한 텍스트가 존재한다.
그러나, 각주를 추가하는 것이 형식적인 것을 허용하기 위한 것이 분명했다; 그것은 위원회가 규범적인 텍스트를 포함하지 않은 각주에 대한 규칙을 어긴 것처럼 보일 뿐이다.각주를 받아들이기 위해서는 각주가 규범적이지 않다는 부분을 정말로 무시하거나, 그렇지 않으면 각주의 결론을 뒷받침하는 방식으로 규범적 텍스트를 해석하는 방법을 강구해야 한다(내가 시도했다가 실패했던 것).
각주를 비준하기 위해 우리가 할 수 있는 최선의 방법은 6.2.5에서 "오버랩 객체"의 집합으로서 조합의 정의에 대해 몇 가지 가정을 하는 것이다.
조합 형식은 각 개체가 선택적으로 지정된 이름과 구별 가능한 유형을 갖는, 조합 형식은 비어 있지 않은 조합 개체 집합의 중첩을 설명한다.
불행하게도 "과잉"이 의미하는 것에 대한 자세한 설명은 없다.개체는 (3.14) "실행 환경에서 데이터 스토리지의 영역으로, 그 내용은 값을 나타낼 수 있다"로 정의된다(위의 "오버랩 객체" 정의로 동일한 스토리지 영역을 식별할 수 있다는 것, 즉 개체는 해당 스토리지 영역과 별개의 ID를 갖는다).합리적인 가정은 (특정 조합 인스턴스의) 조합원이 동일한 저장 영역을 사용한다는 것으로 보인다.
우리가 6.7.2.1/6.5.2.3을 무시하고 각주처럼 조합원이라면 누구나 해당 저장 영역의 내용에 의해 대표되는 값(따라서 유형 펀닝을 허용함)을 반환할 수 있다(일부 사소한 예외를 제외하고는 6.5에서 항상 논란이 되는 엄격한 별칭 규칙)이 오베제에 접근하는 것을 허용하지 않는다.ct는 그 종류에 의한 것 이외에는 없다.「액세스」는 「물체의 가치를 읽거나 수정하는 것」(3.1) 「실행-시간 액션」이기 때문에, 그리고 겹치는 물체의 집합 중 하나를 수정하는 것은 반드시 다른 것을 수정하기 때문에, 엄격한 별칭 규칙은 (그 다음 다른 것을 통해서 읽는지 여부에 관계없이) 조합원에게 쓰는 것으로써 잠재적으로 위반될 수 있다.
예를 들어, 표준의 문구에 의하면, 다음과 같은 것은 불법이다.
union {
int a;
float b;
} u;
u.a = 0; // modifies a float object by an lvalue of type int
int *pa = &u.a;
*pa = 1; // also modifies a float object, without union lvalue involved
(특히, 두 개의 주석 선은 엄격한 별칭 규칙을 위반한다.)
엄밀히 말하면, 각주는 비활동적인 조합원을 읽는 것과 같은 별도의 문제에 대해 말하고 있다. 그러나 위에서 언급한 것과 같이 다른 절과 함께 엄격한 별칭 규정이 그 적용가능성을 심각하게 제한하고 있으며, 특히 일반적으로 (단, 유형의 특정 조합에 대해서만) 형식 연산을 허용하지 않는다는 것을 의미한다.
답답하게도 표준개발을 책임지는 위원회는 일반적으로 조합을 통해 활자연결이 가능해지려는 의도를 갖고 있는 듯하지만, 표준의 본문이 여전히 이를 허용하지 않는 것에 대해서는 전혀 문제가 없어 보인다.
또한 주목할 점은 ( 컴파일러 벤더에 의한) 합의 이해는 노조를 통한 펀칭은 허용되지만, "노조를 통한 액세스"는 "노조를 통한 액세스여야 한다"(예: 위의 예에서 첫 번째 코멘트 라인, 두 번째 라인이 아님)는 것으로 보인다는 점이다.이것이 읽기 및 쓰기 액세스 모두에 적용되어야 하는지는 약간 불명확하며, 표준의 텍스트에 의해 (각주 관련에 대해) 결코 지지되지 않는다.
결론적으로, 노조를 통한 유형의 펀칭이 합법적이라는 것은 대체로 인정되지만(대부분은 "노조를 통해" 접속이 이루어지는 경우에만 허용된다고 생각함), 표준의 문구는 특정 사소한 경우를 제외하고는 모두 금지한다.
인용하는 섹션:
값이 유니언 유형의 개체의 멤버에 저장될 때, 해당 멤버에 해당하지는 않지만 다른 멤버에 해당하는 개체 표현 바이트는 지정되지 않은 값을 취한다.
하지만 주의 깊게 읽어야 해"그 멤버에 해당되지 않는 객체 표현 바이트"는 멤버의 크기를 초과하는 바이트를 가리키는 것으로, 이는 유형 펀닝에 대한 문제 자체가 아니다(조합원에게 쓰는 것이 더 큰 멤버의 "추가" 부분을 그대로 둘 것이라고 가정할 수 없다는 점을 제외한다).
그러나 이는 C99 표준(최소한 초안 n1124)을 위반하는 것으로 보인다. 여기서 섹션 6.2.6.1.7은 일부 내용을 명시하고 있다.C99 하에서는 실제로 이런 행동이 불특정인가?
아니,넌 괜찮아.
값이 유니언 유형의 개체의 멤버에 저장될 때, 해당 멤버에 해당하지는 않지만 다른 멤버에 해당하는 개체 표현 바이트는 지정되지 않은 값을 취한다.
이는 크기가 다른 데이터 블록에 적용된다.즉, 다음이 있을 경우:
union u
{
float f;
double d;
};
f에 무언가를 할당하면 d의 하위 4바이트는 변경되지만 상위 4바이트는 불확실한 상태가 된다.
조합은 주로 유형 펀딩을 위해 존재한다.
'programing' 카테고리의 다른 글
유닛 테스트를 위해 Vuex 게이터를 조롱하면 예기치 않은 결과가 발생함 (0) | 2022.05.23 |
---|---|
uint64_t 인쇄 방법?오류: "허위 후행 '%' 형식" (0) | 2022.05.23 |
npm을 실행하는 경우 빌드 실행 시 VUE에서 build.js 파일만 생성 (0) | 2022.05.23 |
다중 요소 선택 Vue.js (0) | 2022.05.23 |
부울 체크에 xor 연산자를 사용하는 것이 좋은 관행인가? (0) | 2022.05.23 |