13

C++ 에일리어싱 규칙 때문에 (int *)를 char 배열로 지정할 필요가 없습니다.char 배열에 int를 넣는 데 새로운 배치가 필요합니까?

- 다른 질문 - Generic char[] based storage and avoiding strict-aliasing related UB - 배치 재배포를 통해 스토리지를 (다시) 사용할 수있는 것처럼 보입니다. 새로운 배치는 실제로 법적 만드는 데 필요한

위 법적 C++ 입니다
alignas(int) char buf[sizeof(int)]; 

void f() { 
    // turn the memory into an int: (??) from the POV of the abstract machine! 
    ::new (buf) int; // is this strictly required? (aside: it's obviously a no-op) 

    // access storage: 
    *((int*)buf) = 42; // for this discussion, just assume the cast itself yields the correct pointer value 
} 

그래서인가?

+0

관련 항목 : http://stackoverflow.com/questions/38862092/is-it-legal-to-alias-a-char-array-through-a-pointer-to-int –

+0

https://godbolt.org/g/k2nVI9 –

+0

관련성이 높고 잠재적 인 속임수는 다음과 같습니다. https://stackoverflow.com/questions/40873520/reinterpret-cast-creating-a-trivially-default-constructible-object –

답변

12

예, 게재 위치 new이 필요합니다. 그렇지 않으면 엄격한 앨리어싱 (할당은 access)을 위반하게됩니다.

위 내용이 합법적입니까? 거의 (사실상 모든 구현에서 작동 할지라도) 거의. 형 (현재 파괴 된) 배열과 int 객체가 pointer-interconvertible이 아니므로 형 변환을 통해 생성 한 포인터가 객체를 가리 키지 않습니다. std::launder((int*)buf)을 사용하거나 더 나은 아직 배치 new의 반환 값을 사용하십시오.

+1

'interinterpret_cast (buf) = 42'는 엄격한 앨리어스를 위반하지 않습니다. 새로운 int 객체를'int' 형의 lvalue로 접근하기 때문입니다. 포인터 상호 변환은 하나의 "라이브"포인터를 다른 포인터로 변환 할 때 적용됩니다. "죽은"포인터에서 비 목표로 변환 할 때가 아닙니다. 편집 : 나는 거기에'세탁기'가 필요한지 확신 할 수 없다. 내가 아는 마지막 규칙은 여전히 ​​유동적이었습니다. – Potatoswatter

+1

@Potatoswatter 새로운 int 객체는 무엇입니까? 나는 그러한 객체를 만들기위한 새로운 사전 배치가없는 경우에 대해 이야기하고있었습니다. 그리고 포인터를 재 해석 할 때 일반적으로 적용 가능한 포인터 상호 변환 성을 읽습니다. 그럼에도 불구하고, 캐스트를 사용하여 연산에 의해 생성 된 포인터는 P0137에 정의 된대로 새로운 객체를 가리 키지 않으므로'launder'가 필요합니다. – Columbo

+0

[basic.lval] 특정 유형의 lvalues를 제외하고 객체에 액세스하는 것을 금지합니다. 아직 개체가 존재하는지 여부에 대한 문제는 다루지 않습니다. [basic.life]/C++의 6은 14 일 동안 'reinterpret_cast'를 통해 할당을 허용합니다. 이것은 P0137에 의해 제거되므로 C++ 17은 새로운 배치를 요구합니다. 당신은 포인터 상호 변환성에 대해 옳습니다. P0137은'void *'의'static_cast'를 통해'reinterpret_cast'에 연결합니다. 따라서 '세탁물'은 살아있는 물건에 접근하는 데 필요합니다 (그러나 결코 물건을 세탁하지 마십시오). – Potatoswatter

-3
*((int*)buf) = 42; 

int 좌변와 함께 int를 기록, 그래서 처음에는 앨리어싱 문제가 없다.