2010-07-07 5 views
2
struct Vector 
{ 
    float x, y, z; 
}; 

func(Vector *vectors) {...} 

usage: 
load float *coords = load(file); 
func(coords); 

C++의 구조 정렬에 대한 질문이 있습니다. 나는 일련의 점들을 함수 func()에 전달할 것이다. 위와 같은 방법으로 할 수 있습니까, 아니면 플랫폼 의존적 인 동작에 의존하고 있습니까? (적어도 현재 컴파일러에서 작동합니다.) 누군가 주제에 대해 좋은 기사를 추천 할 수 있습니까?C++의 구조 정렬

또는 파일에서 데이터를로드하는 동안 직접 점 집합을 만드는 것이 더 좋습니까?

감사합니다.

+2

귀하의 게시물을 읽기가 매우 어렵습니다. –

+3

그건 당신이 지금 당장 가지고있는 C++가 아닙니다. 사용법은 컴파일되지 않으며 문제의 벡터를 어떻게 사용하는지 보여주지 않습니다. load()가 수락하고 반환하는 것을 보여주기 위해 사용법을 수정하십시오. 또한 coords는 예제에서 float 포인터이고, func는 벡터 포인터를 원합니다. –

+1

파일에 이진 데이터를 쓰고 그 내용을 읽을 수 없습니다. 기계 사이에는 너무 많은 변형이 있습니다. 데이터를 직렬화 (텍스트로 쓰는 것)하는 것이 훨씬 쉬우 며 입력시에 직렬화하여 구조에 다시 적용하는 것이 더 쉽습니다. –

답변

3

구조체 정렬은 구현에 따라 다릅니다. 그러나 대부분의 컴파일러는 구조체를 "패킹"(즉, 필드 사이에 패딩 바이트없이 메모리에 정렬)하도록 지정하는 방법을 제공합니다. 예를 들어 :

struct Vector { 
    float x; 
    float y; 
    float z; 
} __attribute__((__packed__)); 

위의 코드는 쉽게 파일에 덤프하고 다시 나중에 읽을 수있어 메모리의 구조를 포장 할 수있는 GCC 컴파일러의 원인이됩니다. 이렇게하는 정확한 방법은 컴파일러에 따라 다를 수 있습니다 (세부 사항은 컴파일러의 설명서에 나와 있습니다).

필자는 항상 포장 구조체의 멤버를 표시 할 순서에 대해 명확히하기 위해 별도의 줄에 나열합니다. 대부분의 컴파일러의 경우 이것은 float x, y, z;과 동일해야하지만 구현에 종속적 인 동작인지 여부는 확실하지 않습니다. 안전을 위해 한 줄에 하나의 선언문을 사용합니다.

파일에서 데이터를 읽는 경우 데이터를 확인한 후 func으로 전달해야합니다. 데이터 정렬 강화의 양은 입력 유효성 검사의 부족을 보완하지 못합니다.

편집 :

더 코드를 읽은 후, 더 당신이 뭘 하려는지 이해합니다. 세 개의 float 값을 포함하는 구조가 있고이 배열이 부동 소수점 배열 인 것처럼 float*으로 액세스하고 있습니다. 이것은 매우 나쁜 습관입니다. 컴파일러가 구조의 처음이나 끝 부분에서 어떤 패딩을 사용하는지 알 수 없습니다. 패킹 된 구조라도 구조체를 배열처럼 취급하는 것은 안전하지 않습니다. 배열이 원하는 경우 배열을 사용하십시오. 가장 안전한 방법은 파일에서 데이터를 읽어서 struct Vector 유형의 새 객체에 저장하고 func으로 전달하는 것입니다. func이 인수로 struct Vector*을 취하도록 정의하고 컴파일러가 귀찮게하지 않고 float*을 전달할 수 있도록 허용하는 경우 실제로 의존하지 않아야하는 구현에 의존하는 동작입니다. 모든

+1

패킹/구조 정렬 외에도 엔디안 문제를 잊지 마세요! –

0

첫째, 귀하의 예제 코드는 나쁜 : 당신은 Vector 객체에 대한 포인터 대신 플로트 VAR에) (포인터를 FUNC를 전달하는

load float *coords = load(file); 
func(coords); 

.

두 번째로 Vector의 전체 크기는 (sizeof (float) * 3), 즉 12 바이트입니다.
구조체의 aligment를 제어하는 ​​방법을 보려면 컴파일러의 설명서를 참조하고 16 바이트로 설정하면됩니다.
그런 식으로 하나의 벡터가 들어있는 파일의 크기가 항상 16 바이트이며 16 바이트 만 읽어야한다는 것을 알 수 있습니다.

편집 :
확인 MSVC9's align capabilities을 확인하십시오.

+0

Vector가 12 바이트라고 가정하지 마십시오. 컴파일러는 언제든지 패딩을 추가 할 수 있습니다. 컴파일러는 이러한 객체의 배열에 가능한 한 효율적으로 액세스 할 수 있도록 크기와 정렬을 설정합니다. 컴파일러와 싸우고 구조에 특정 크기를 설정하려고하면 생산성이 떨어집니다. –

+0

@Martin : 당신은 100 % 정확합니다. 그러나 나의 대답은이 특정 질문에 따른 것입니다. 물론 "12"는 단지 예일뿐입니다. – Poni

0

포인터에 의해 전달보다 참조에 의해 전달을 선호 :

void func(Vector& vectors) 
{ /*...*/ } 

포인터와 참조 사이 여기에서 차이가 포인터가 메모리에 이상한 곳으로 NULL 또는 포인트가 될 수 있다는 것입니다. 참조는 기존 객체를 참조합니다.

조정에 관한 한 신경 쓰지 마십시오. 컴파일러는 이것을 자동으로 처리합니다 (최소한 메모리 정렬).

파일의 이진 데이터 정렬에 관해서는 "직렬화"라는 용어를 검색하십시오.

2

연산자 >> 추출 과부하를 사용하십시오.

std::istream& operator>>(std::istream& stream, Vector& vec) { 
    stream >> vec.x; 
    stream >> vec.y; 
    stream >> vec.z; 
    return stream; 
} 

지금 당신은 할 수 있습니다 :

std::ifstream MyFile("My Filepath", std::ios::openmodes); 
Vector vec; 
MyFile >> vec; 
func(&vec); 
+0

스트림 운영자로부터 값을 반송하는 것을 잊어 버렸습니다. –

+2

아마도 스트림 운영자가 스트림을 반환하도록해야합니다. 이렇게하면 스트림 작업을 연결할 수 있습니다. –

0

쓰기 이진 데이터가 컴퓨터 사이가 아닌 휴대용입니다.
유일한 휴대용 정보는 텍스트입니다 (심지어 모든 시스템이 동일한 텍스트 형식을 사용하는 것은 아닙니다. (운좋게도 대부분 127 ASCII 문자를 받아 들여 곧 Unicode와 같은 것으로 표준화 할 것입니다.)

파일에 데이터를 쓰려면 파일의 정확한 형식을 결정해야하며 그런 다음 해당 형식의 데이터를 읽을 코드를 작성하고 해당 형식의 특정 하드웨어 표현으로 변환하십시오. 형식은 바이너리 일 수도 있고 직렬화 된 텍스트 형식 일 수도 있습니다 (디스크 입출력 속도가 아마도 제한 요소가 될 수 있기 때문에) 성능면에서별로 중요하지 않습니다. 간결성 측면에서 보면 이진 형식이 더 효율적 일 것입니다. 각 플랫폼에서 디코딩 기능을 작성하는 것은 분명히 텍스트 형식이 그것의 t는 이미 시내로 건축된다.

간단한 해결책 :
직렬화 된 텍스트 형식에 대한 읽기/쓰기.
정렬 문제도 없습니다.

#include <algorithm> 
#include <fstream> 
#include <vector> 
#include <iterator> 

struct Vector 
{ 
    float x, y, z; 
}; 
std::ostream& operator<<(std::ostream& stream, Vector const& data) 
{ 
    return stream << data.x << " " << data.y << " " << data.z << " "; 
} 
std::istream& operator>>(std::istream& stream, Vector& data) 
{ 
    return stream >> data.x >> data.y >> data.z; 
} 


int main() 
{ 
    // Copy an array to a file 
    Vector data[] = {{1.0,2.0,3.0}, {2.0,3.0,4.0}, { 3.0,4.0,5.0}}; 
    std::ofstream file("plop"); 
    std::copy(data, data+3, std::ostream_iterator<Vector>(file)); 



    // Read data from a file. 
    std::vector<Vector> newData; // use a vector as we don't know how big the file is. 
    std::ifstream input("inputFile"); 
    std::copy(std::istream_iterator<Vector>(input), 
       std::istream_iterator<Vector>(), 
       std::back_inserter(newData) 
      ); 
} 
관련 문제