2014-04-04 6 views
2

포인터의 배열을 정렬하기 위해 포인터를 int로 취급하는 것이 좋습니다.포인터의 배열 정렬

qsort(ptrs, n, sizeof(void*), int_cmp); 

나는 관계없이 포인터가 가리키는 물건의 종류, 어떤 중복이 있는지 확인하기 위해 ptrs을 정렬 할, 그래서를 qsort는 그 일의 전조이다.

int_cmp()은 꽤 표준입니다.

int int_cmp(const void *a, const void *b) 
{ 
    const int *ia = (const int *)a; // casting pointer types 
    const int *ib = (const int *)b; 

    /* integer comparison: returns negative if b > a 
    and positive if a > b */ 
    return *ia - *ib; 
} 
내 단위 테스트에서 작동하는 것 같다하지만 난 간과 할 수 이러한 시나리오에 대한 문제가 발생할 수 있습니다 int로서 PTR을 고려하는 이유 몇 가지 이유가

?

+2

아니, 당신은'int'로 포인터를 취급 할 수 없다. 포인터의 크기는'int'의 크기와 같지 않을 수 있습니다. 또한 직접 비교하거나 산술 표현식 (예 : 구조체)에서 사용할 수없는 많은 유형의 데이터가 있음을 기억하십시오. –

+0

좋아, 난 그냥 ptr_cmp() 함수를 작성할 필요가 ptr에 캐스팅, 나는 그것을 역 참조해야하므로 무효 ptr 수 없으므로 어쩌면 char ptr 사용할 수 있습니까? 내가 포인터를 무엇을 가리키는 지 상관없이 어떤 ptrs 배열을 정렬 할 수 있도록 일반 있습니다. – bph

+2

포인터를 보유 할 수있는 유일한 정수 변수는'intptr_t' 및'uintptr_t'입니다. –

답변

3

주소로 포인터를 정렬하려면을 원하지 않는 한 아예 옳지 않습니다. 실제 주소는 거의 의미가 없으므로 매우 드뭅니다.

중복 포인터를 탐지하기 위해서는 잘 정의 된 포인터 만 비교하면됩니다.

아마 uintptr_t를 사용하여 솔루션을 갈 것입니다 :

static int order_pointers(const void *pa, const void *pb) 
{ 
    const uintptr_t a = *(void **) pa, b = *(void **) pb; 

    return a < b ? -1 : a > b; 
} 

이 테스트를하지 않은,하지만 그 같은 작업을해야합니다.

랜덤 포인터를 유효하게 비교할 수 없기 때문에 uintptr_t으로 변환해야합니다. 나는 quoth C99 표준 초안, §6.5.8.5 : 두 개의 포인터를 비교하면

, 결과는 개체의 주소 공간의 상대적인 위치에 따라 달라은 지적했다. 객체 또는 불완전 유형에 대한 두 포인터가 모두 인 경우 동일한 객체를 가리 키거나 둘 다 같은 배열 객체의 마지막 요소를 가리키는 경우 은 동일합니다. 가리키는 개체가 동일한 집계 개체의 멤버 인 경우 나중에 선언 된 구조체 멤버에 대한 포인터가 구조체의 앞부분에 선언 된 멤버의 포인터보다 크고 더 큰 하위 문자 값을 가진 배열 요소에 대한 포인터는 다음 요소의 포인터보다 큽니다. 더 작은 첨자 값을 가진 같은 배열. 같은 공용체 객체의 멤버에 대한 모든 포인터는 동등한 값을 비교합니다. 표현식 P가 배열 객체의 요소를 가리키고 표현식 Q가 동일한 배열 객체의 마지막 요소 인 을 가리키는 경우 포인터 표현식 Q + 1은 보다 큰 것으로 나타납니다. 그 밖의 경우에는 다음과 같이 동작합니다. 정의되지 않았습니다.

여기에서 적용되는 마지막 문장이 굵은 글꼴입니다.

+0

네, 정확히 내가 뭘하고 싶은지 - 정렬 * 주소 * 순서에 따라 여부를 내가 배열에 중복 ptrs 여부를 평가하는 예 2 개의 주소가 같음 – bph

+0

'a a b'를 의미하셨습니까? -1 : a> b; 그렇죠? – ajay

+1

@ajay 네, 오타가 날 수 있습니다. 고침, 고마워! – unwind

2

당신이 비교를 사용하여 제공하지 뺄셈, 당신은 무효 포인터를 고수 할 수 다음은 간단한 테스트를 위해 일한 다음 :

int int_cmp(const void *pa, const void *pb) 
{ 
    const void* a = *(void**)pa ; 
    const void* b = *(void**)pb ; 

    if(a < b) return -1 ; 
    if(a > b) return 1 ; 
    return 0 ; 
} 
+0

-1, 이것은 정의되지 않은 동작입니다. 나 혼자만 경적을 울리지 마라.하지만 ... 내 대답을 보라. – unwind

+0

void 포인터를 비교하는 것은 UB입니까? @unwind – alk

+1

@alk 예, 포인터가 동일한 "개체"를 가리키고 있다는 것을 알지 못하는 경우에는 내 대답의 표준 인용문을 참조하십시오. – unwind