2014-10-09 5 views
0

프로그램을 작성 중이며 구조 요소의 두 주소 사이의 차이를 계산해야합니다. 죄송합니다 명확하지 않은 경우 일부 코드가 더 명확 할 수 있습니다.동일한 구조의 두 요소를 뺍니다?

코드에는 일부 MPI 요소가 있지만 내 문제는 아닙니다.

typedef struct Str { 
    std::vector<int> itab; 
    std::vector<char> ctab; 
} s_str; 

int main(int argc, char **argv) 
{ 
    s_str *struc1 = new s_str(); 

    MPI_Datatype Strtype; 
    int count = 2; 
    int lengths[2] = { 8, 8 }; 
    MPI_Aint disp[2]; 
    disp[0] = &struc1->itab - &struc1; 
    disp[1] = &struc1->ctab - &struc1; 
    MPI_Datatype types[2] = { MPI_INT, MPI_CHAR }; 
    MPI_Type_create_struct(count, lengths, disp, types, &Strtype); 
    MPI_Type_commit(&Strtype); 

    (...) 
} 

문제는이 라인에서 일어나는 모든의

MPI_Aint disp[2]; 
disp[0] = &struc1->itab - &struc1; 
disp[1] = &struc1->ctab - &struc1; 

첫째, MPI_Aint은 (문서에서 가져온)는 "유효한 주소를 가지고 C 타입"입니다. 여기서 내가하려고하는 것은 struc1-> itab와 struc1 주소의 차이를 계산하는 것입니다.

는 여기에 내가지고있어 오류입니다 : 여기에 포함 된 유형 std::vector<int>*s_str** 때문에

tmp2.cpp: In function ‘int main(int, char**)’: 
tmp2.cpp:30:30: erreur: invalid operands of types ‘std::vector<int>*’ and ‘s_str** {aka Str**}’ to binary ‘operator-’ 
tmp2.cpp:31:30: erreur: invalid operands of types ‘std::vector<char>*’ and ‘s_str** {aka Str**}’ to binary ‘operator-’ 

내가, 내가 제대로 주소를 액세스 할 수 없습니다 것 같아. 적절한 방법은 무엇입니까?

세부 정보 : MPI-I/O를 사용하여 파일을 작성해야합니다. MPI에게 각 proc이 전체 데이터 세트를 작성하는 데 필요한 공간을 알려주는 것입니다. 기본적으로 MPI-I/O를 사용하여 파일에 사용자 정의 구조체의 내용을 작성하려고합니다. 이유가 여기 있습니다.

+2

'struc1'은 이미 * 주소 (포인터)이므로 address-of 연산자를 사용하면 주소 주소 (포인터에 대한 포인터)를 얻을 수 있습니다. 예를 들어를 사용하여 '수정'하면 '& struc1-> itab-struc1' 그러면 주소를 얻지 못하면 구조체 안에 itab 멤버의 * offset *을 얻습니다.이 구조체에는 표준 ['offsetof']이 있습니다 (http : // en .cppreference.com/w/cpp/types/offsetof) 매크로가 이미 있습니다. –

+0

아, 구조체에 주소 연산자를 사용하지 않는 등의 '수정'을 사용해도 형식이 실제로 호환되지 않으므로 오류가 발생할 수 있으며 포인터를 캐스팅해야합니다. 또는 원하는 경우 offset을 얻으려면'offsetof' 매크로를 사용하십시오. –

+2

@JoachimPileborg'offsetof'는 클래스가 표준 레이아웃이 아닌 한 UB입니다. 그리고'std :: vector'는 표준 레이아웃이 아니며 둘 다'Str'이 아닙니다. –

답변

0

이것은 내가 사용했던 것입니다.

MPI_Aint disp[2] = { 0, (uintptr_t)&(struc1->ctab[0]) - (uintptr_t)&(struc1->itab[0]) }; 
MPI_Aint disp[2] = { 0, sizeof (std::vector<int>) + sizeof (std::vector<char>) }; 
// Why do both of these solutions work ? 

사람이 내 경우와 특정하지 있는지 확인 수 : 두 솔루션은 나는 그들이 같은 의미를 생각하지 않기 때문에,하지만 작동 이유는 나도 몰라 내 프로젝트에서 작동 그 방법들은 완전히 이상하거나/나쁘지 않습니까?

0

이 시도 :

disp[0] = ((char *) &(struc1->itab)) - ((char *) struc1); 
disp[1] = ((char *) &(struc1->ctab)) - ((char *) struc1); 
+1

포인터 연산은 UB입니다. –

1

나는 당신의 추론은 당신이 벡터가 다른 곳으로 배치 될 수있는 벡터의 실제 요소가있는 곳의 주소를 제공하는 경우에도, 조금 잘못 생각합니다.

예를 들어 시도해보십시오.

s_str struc1; 
struc1.itab.push_back(0); 
printf("struc1.itab %p\n", (void*)&(struc1.itab)); 
printf("struc1.ctab %p\n", (void*)&(struc1.ctab)); 
printf("struc1.itab[0] %p\n", (void*)&(struc1.itab[0])); 
printf("struc1 %p\n", (void*)&struc1); 

struc1.itab 000000000022fde0 
struc1.ctab 000000000022fdf8 
struc1.itab[0] 0000000000327f40 
struc1 000000000022fde0 

어쩌면 원래 두 개의 정상적인 c- 배열을 가진 구조체가 있었습니까?

typedef struct 
{ 
    int itab[100]; 
    char ctab[100]; 
} struc1; 

그러면 사용자가하는 일에 더 많은 의미가 있습니다.

+1

나는 그것이 옳다고 생각한다. OP는 벡터 자체의 주소가 아니라 벡터의 데이터 요소 중 첫 번째 요소의 주소를 거의 필요로합니다. –

0

휴대용 MPI 방법은 다음과 같습니다 std::vector가 힙에 미치는 요소에 대한 메모리를 할당하기 때문에

MPI_Aint base; 

MPI_Get_address(&struc1, &base); 
MPI_Get_address(&struc1->itab, &disp[0]); 
disp[0] -= base; 
MPI_Get_address(&struc1->ctab, &disp[1]); 
disp[1] -= base; 

어쨌든,이 작동하지 않습니다. 절대 주소를 사용

MPI_Aint disp[2]; 

// N.B. both displacements are ABSOLUTE addresses 
MPI_Get_address(&struc1->itab[0], &disp[0]); 
MPI_Get_address(&struc1->ctab[0], &disp[1]); 

MPI_Type_create_struct(count, lengths, disp, types, &Strtype); 
MPI_Type_commit(&Strtype); 

MPI_Send(MPI_BOTTOM, 1, Strtype, ...); 

MPI_Type_free(&Strtype); 

구조 유형이 구성되어 있으므로 MPI_BOTTOMMPI_Send 호출에 사용되어야한다 : 힙 할당 주소 공간 '과정에서 완전히 임의의 위치에 끝날 수도로, 하나는 약간 다른 접근 방식을 사용해야합니다 (MPI_BOTTOM은 버퍼 주소가 프로세스의 주소 공간의 맨 아래임을 나타냄). 이 구조체 형식의 인스턴스를 하나만 보내는 경우 작동하므로 형식을 보내기 호출 후 즉시 소멸됩니다. 원칙적으로, 전송할 각 구조 인스턴스에 대해 새로운 데이터 유형을 작성하는 것은 데이터를 전송하는 것이 유형 생성 및 삭제보다 훨씬 비싼 작업이므로 큰 문제는 아닙니다.

관련 문제