2016-10-03 4 views
0

another question에 응답하려고 시도한 결과 std::memcpy()을 사용하여 char 버퍼에 제네릭 형식을 저장하는 솔루션을 제안했습니다.일반 오래된 데이터와`std :: memcpy '정렬 문제

내가 의심하는 점은 POD를 저장할 때 발생할 수있는 메모리 정렬 문제에 관한 것입니다. POD 유형이 아니라는 것을 알고 있습니다 (std::string은 매우 위험합니다).

간단히 말해서 다음 프로그램에 메모리 정렬 문제가 있습니까?

그렇다면 안전 한 POD 값을 char 버퍼에 저장하는 것과 비슷한 것을 쓸 수 있습니까? 그리고 어떻게?

#include <cstring> 
#include <iostream> 

int main() 
{ 
    char buffer[100]; 

    double d1 { 1.2 }; 

    std::memmove(buffer + 1, & d1, sizeof(double)); 

    double d2; 

    std::memmove(& d2, buffer + 1, sizeof(double)); 

    std::cout << d2 << std::endl; 

    return 0; 
} 
+0

이렇게하면됩니다. 일반적으로 sizeof()를 고정 버퍼보다 ​​작게해야하지만, 물론 double은 여기에 사용 된 100보다 작습니다. – Gregg

+0

@ 그레그 - 물론; 버퍼의 크기에 대한 의문을 피하기 위해'100'을 사용했습니다. – max66

답변

5

안전합니다.

임의의 사소 복사 가능한 유형 T 들어

[basic.types]/2:, 만약 도 obj1obj2는베이스 클래스 하위 개체 인 별개 T 개체 obj1obj2, 행 T 차례로 두 개의 포인터 하부 바이트 (170)를 구성하는 경우 obj1은 을 obj2으로 복사 한 후 obj2은 이후에 obj1과 동일한 값을 유지해야합니다.

double은 쉽게 복사 할 수 있으므로 코드는 잘 정의되어 있습니다.

3

정렬되지 않은 버퍼간에 복사 할 수 있습니다. 당신이 할 수없는 것은 버퍼를 double *로 캐스팅 한 다음 메모리의 값을 double로 직접 연산하는 것입니다. 정렬 문제로 인해 종종 오류가 발생합니다.

+2

"* 기술적으로 임의의 바이트를 char에 할당하는 것은 트랩 표현 때문에 정의되지 않았습니다. *"표준에 맞지 않습니다. [basic.types]/2는 객체의 사소한 복사에'char' 또는'unsigned char'을 사용할 수 있다고 말합니다. –

+0

표준의 결함입니다. char는 트랩 표현이 허용되며 절 중 하나가 틀립니다. 사실 저자는 끄덕이고 타입은 unsigned char 여야합니다. –

+1

결함이 없습니다. 'char'는 서명되거나 서명되지 않는 것이 허용됩니다. 'signed char'는 트랩 표현을 가질 수도 그렇지 않을 수도 있습니다. 구현이 표준과 일치하도록하기 위해서'signed char'가 함정에 빠질 수 있다면'char' *에 서명해서는 안됩니다 *. 따라서 2의 보수로 서명 된'char' 타입은 완벽하게 유효합니다. 'char'에 대한 UTF-8 요구 사항 ('char'과'unsigned char' 사이의 UTF-8 코드를 변환 할 수 있다는 것은'char'가 트랩을 요구하지 않습니다)과 같은 요구 사항을 가진 표준에 다른 장소가 있습니다. –